eru-grid 0.0.43 → 0.0.45
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/fesm2022/eru-grid.mjs +152 -91
- package/fesm2022/eru-grid.mjs.map +1 -1
- package/package.json +1 -1
- package/types/eru-grid.d.ts +41 -2
package/fesm2022/eru-grid.mjs
CHANGED
|
@@ -8,26 +8,26 @@ import * as i3 from '@angular/material/input';
|
|
|
8
8
|
import { MatInputModule } from '@angular/material/input';
|
|
9
9
|
import * as i1$2 from '@angular/material/button';
|
|
10
10
|
import { MatButtonModule } from '@angular/material/button';
|
|
11
|
-
import * as
|
|
11
|
+
import * as i2$1 from '@angular/material/checkbox';
|
|
12
12
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
13
|
-
import * as i2$
|
|
13
|
+
import * as i2$4 from '@angular/material/slider';
|
|
14
14
|
import { MatSliderModule } from '@angular/material/slider';
|
|
15
|
-
import * as i2$
|
|
15
|
+
import * as i2$2 from '@angular/material/icon';
|
|
16
16
|
import { MatIconModule } from '@angular/material/icon';
|
|
17
|
-
import * as i2$
|
|
17
|
+
import * as i2$5 from '@angular/common';
|
|
18
18
|
import { CommonModule, DatePipe } from '@angular/common';
|
|
19
|
-
import * as i4$
|
|
19
|
+
import * as i4$1 from '@angular/material/datepicker';
|
|
20
20
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
21
21
|
import * as i1$1 from '@angular/material/core';
|
|
22
|
-
import { NativeDateAdapter, DateAdapter, MAT_DATE_FORMATS, MatNativeDateModule, MatOptionModule } from '@angular/material/core';
|
|
22
|
+
import { NativeDateAdapter, DateAdapter, MAT_DATE_FORMATS, MatNativeDateModule, MatOptionModule, MatPseudoCheckboxModule } from '@angular/material/core';
|
|
23
23
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
24
24
|
import * as i1$3 from '@angular/cdk/overlay';
|
|
25
25
|
import { OverlayModule } from '@angular/cdk/overlay';
|
|
26
26
|
import * as i4 from '@angular/material/tooltip';
|
|
27
27
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
28
|
-
import * as i4$
|
|
28
|
+
import * as i4$2 from '@angular/material/tabs';
|
|
29
29
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
30
|
-
import * as i2$
|
|
30
|
+
import * as i2$3 from '@angular/material/select';
|
|
31
31
|
import { MatSelectModule } from '@angular/material/select';
|
|
32
32
|
import { polyfillCountryFlagEmojis } from 'country-flag-emoji-polyfill';
|
|
33
33
|
import { MatChipsModule } from '@angular/material/chips';
|
|
@@ -74,6 +74,8 @@ const PRESET_CONFIG_DEFAULTS = {
|
|
|
74
74
|
* tool_tip per-grid header help text
|
|
75
75
|
* is_hidden hiding a column in one grid should not require
|
|
76
76
|
* hiding the field in the data model
|
|
77
|
+
* searchable whether a picker needs a filter box depends on how
|
|
78
|
+
* many options this grid shows, not on the field
|
|
77
79
|
* dateTimeFormat legacy alias; the model writes `date_format`
|
|
78
80
|
*/
|
|
79
81
|
const INHERITED_FIELD_KEYS = [
|
|
@@ -104,7 +106,7 @@ const INHERITED_FIELD_KEYS = [
|
|
|
104
106
|
// Phone
|
|
105
107
|
'default_country',
|
|
106
108
|
// Cardinality and picker behaviour
|
|
107
|
-
'multiple', '
|
|
109
|
+
'multiple', 'max_avatars', 'people_card', 'show_people_card',
|
|
108
110
|
// Governance — authored in the data model, never overridden per grid
|
|
109
111
|
'is_pii', 'is_ephi', 'is_pf', 'to_encrypt', 'is_unique', 'unq_sa',
|
|
110
112
|
'system_validate', 'ssv_api', 'can_group', 'default_group',
|
|
@@ -126,6 +128,46 @@ function normalizeDatatype(datatype) {
|
|
|
126
128
|
const key = String(datatype ?? '');
|
|
127
129
|
return DATATYPE_ALIASES[key] ?? key;
|
|
128
130
|
}
|
|
131
|
+
/** Shown when a value has no colour of its own. */
|
|
132
|
+
const STATUS_PILL_FALLBACK = {
|
|
133
|
+
background: 'white',
|
|
134
|
+
border: 'black',
|
|
135
|
+
text: 'black',
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* The colours for a status pill, from the single colour the data model gives it.
|
|
139
|
+
*
|
|
140
|
+
* The fill is lightened 90% toward white and the text darkened 30%, with the
|
|
141
|
+
* border left at full saturation. That is what keeps a pale palette entry
|
|
142
|
+
* readable: using the raw colour as text on a tint of itself puts same-hue on
|
|
143
|
+
* same-hue, and the pale half of a palette becomes unreadable.
|
|
144
|
+
*
|
|
145
|
+
* Exported from here — rather than living in the grid's status cell where it
|
|
146
|
+
* started — because eru-studio's status badge and chip list paint the same
|
|
147
|
+
* values, and three copies of this arithmetic is three ways for one field to
|
|
148
|
+
* look different depending on which control renders it.
|
|
149
|
+
*/
|
|
150
|
+
function statusPillColors(color) {
|
|
151
|
+
const hex = String(color ?? '').replace('#', '');
|
|
152
|
+
const expanded = hex.length === 3 ? hex.split('').map(c => c + c).join('') : hex;
|
|
153
|
+
if (expanded.length !== 6)
|
|
154
|
+
return { ...STATUS_PILL_FALLBACK };
|
|
155
|
+
const value = parseInt(expanded, 16);
|
|
156
|
+
if (isNaN(value))
|
|
157
|
+
return { ...STATUS_PILL_FALLBACK };
|
|
158
|
+
const r = (value >> 16) & 255;
|
|
159
|
+
const g = (value >> 8) & 255;
|
|
160
|
+
const b = value & 255;
|
|
161
|
+
const lighten = 0.9;
|
|
162
|
+
const darken = 0.3;
|
|
163
|
+
const lit = (channel) => Math.min(255, Math.round(channel + (255 - channel) * lighten));
|
|
164
|
+
const dark = (channel) => Math.round(channel * (1 - darken));
|
|
165
|
+
return {
|
|
166
|
+
background: `rgb(${lit(r)}, ${lit(g)}, ${lit(b)})`,
|
|
167
|
+
border: `#${expanded}`,
|
|
168
|
+
text: `rgb(${dark(r)}, ${dark(g)}, ${dark(b)})`,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
129
171
|
/** Short month names, for the `MMM` token. */
|
|
130
172
|
const MONTH_SHORT_NAMES = [
|
|
131
173
|
'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
@@ -4632,21 +4674,21 @@ function abbreviateNumber$1(num, system, decimals) {
|
|
|
4632
4674
|
};
|
|
4633
4675
|
if (system === 'lacs') {
|
|
4634
4676
|
if (abs >= 1e7)
|
|
4635
|
-
return `${sign}${trim(abs / 1e7)}Cr`;
|
|
4677
|
+
return `${sign}${trim(abs / 1e7)} Cr`;
|
|
4636
4678
|
if (abs >= 1e5)
|
|
4637
|
-
return `${sign}${trim(abs / 1e5)}L`;
|
|
4679
|
+
return `${sign}${trim(abs / 1e5)} L`;
|
|
4638
4680
|
if (abs >= 1e3)
|
|
4639
|
-
return `${sign}${trim(abs / 1e3)}k`;
|
|
4681
|
+
return `${sign}${trim(abs / 1e3)} k`;
|
|
4640
4682
|
return `${sign}${trim(abs)}`;
|
|
4641
4683
|
}
|
|
4642
4684
|
if (abs >= 1e12)
|
|
4643
|
-
return `${sign}${trim(abs / 1e12)}tn`;
|
|
4685
|
+
return `${sign}${trim(abs / 1e12)} tn`;
|
|
4644
4686
|
if (abs >= 1e9)
|
|
4645
|
-
return `${sign}${trim(abs / 1e9)}bn`;
|
|
4687
|
+
return `${sign}${trim(abs / 1e9)} bn`;
|
|
4646
4688
|
if (abs >= 1e6)
|
|
4647
|
-
return `${sign}${trim(abs / 1e6)}mn`;
|
|
4689
|
+
return `${sign}${trim(abs / 1e6)} mn`;
|
|
4648
4690
|
if (abs >= 1e3)
|
|
4649
|
-
return `${sign}${trim(abs / 1e3)}k`;
|
|
4691
|
+
return `${sign}${trim(abs / 1e3)} k`;
|
|
4650
4692
|
return `${sign}${trim(abs)}`;
|
|
4651
4693
|
}
|
|
4652
4694
|
class CurrencyComponent {
|
|
@@ -4870,21 +4912,21 @@ function abbreviateNumber(num, system, decimals) {
|
|
|
4870
4912
|
};
|
|
4871
4913
|
if (system === 'lacs') {
|
|
4872
4914
|
if (abs >= 1e7)
|
|
4873
|
-
return `${sign}${trim(abs / 1e7)}Cr`;
|
|
4915
|
+
return `${sign}${trim(abs / 1e7)} Cr`;
|
|
4874
4916
|
if (abs >= 1e5)
|
|
4875
|
-
return `${sign}${trim(abs / 1e5)}L`;
|
|
4917
|
+
return `${sign}${trim(abs / 1e5)} L`;
|
|
4876
4918
|
if (abs >= 1e3)
|
|
4877
|
-
return `${sign}${trim(abs / 1e3)}k`;
|
|
4919
|
+
return `${sign}${trim(abs / 1e3)} k`;
|
|
4878
4920
|
return `${sign}${trim(abs)}`;
|
|
4879
4921
|
}
|
|
4880
4922
|
if (abs >= 1e12)
|
|
4881
|
-
return `${sign}${trim(abs / 1e12)}tn`;
|
|
4923
|
+
return `${sign}${trim(abs / 1e12)} tn`;
|
|
4882
4924
|
if (abs >= 1e9)
|
|
4883
|
-
return `${sign}${trim(abs / 1e9)}bn`;
|
|
4925
|
+
return `${sign}${trim(abs / 1e9)} bn`;
|
|
4884
4926
|
if (abs >= 1e6)
|
|
4885
|
-
return `${sign}${trim(abs / 1e6)}mn`;
|
|
4927
|
+
return `${sign}${trim(abs / 1e6)} mn`;
|
|
4886
4928
|
if (abs >= 1e3)
|
|
4887
|
-
return `${sign}${trim(abs / 1e3)}k`;
|
|
4929
|
+
return `${sign}${trim(abs / 1e3)} k`;
|
|
4888
4930
|
return `${sign}${trim(abs)}`;
|
|
4889
4931
|
}
|
|
4890
4932
|
class NumberComponent {
|
|
@@ -6165,7 +6207,7 @@ class CheckboxComponent {
|
|
|
6165
6207
|
}
|
|
6166
6208
|
}
|
|
6167
6209
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: CheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6168
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: CheckboxComponent, isStandalone: true, selector: "eru-checkbox", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", change: "change", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, ngImport: i0, template: "<div \n class=\"checkbox-container\"\n [class.checkbox-active]=\"isActive()\"\n [class.checkbox-display-editable]=\"isEditable() && !isActive()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable() && !isActive()) {\n <span class=\"checkbox-drillable\" (click)=\"onDrillableClick($event)\">\n <mat-checkbox \n [ngModel]=\"currentValue()\" \n (ngModelChange)=\"onValueChange($event)\"\n [disabled]=\"true\">\n {{label()}}\n </mat-checkbox>\n </span>\n } @else {\n <mat-checkbox \n [ngModel]=\"currentValue()\" \n (ngModelChange)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n [disabled]=\"!isEditable() || !isActive()\">\n {{label()}}\n </mat-checkbox>\n }\n</div>\n", styles: [":host{display:block;height:100%;width:100%}.checkbox-container{display:flex;align-items:center;justify-content:center;height:100%;width:100%;padding:4px;cursor:default}.checkbox-container.checkbox-display-editable{cursor:pointer}.checkbox-container.checkbox-display-editable:hover{background-color:#0000000a}.checkbox-container.checkbox-active{cursor:default}.checkbox-drillable{cursor:pointer;color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease}\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: MatCheckboxModule }, { kind: "component", type:
|
|
6210
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: CheckboxComponent, isStandalone: true, selector: "eru-checkbox", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", change: "change", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, ngImport: i0, template: "<div \n class=\"checkbox-container\"\n [class.checkbox-active]=\"isActive()\"\n [class.checkbox-display-editable]=\"isEditable() && !isActive()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable() && !isActive()) {\n <span class=\"checkbox-drillable\" (click)=\"onDrillableClick($event)\">\n <mat-checkbox \n [ngModel]=\"currentValue()\" \n (ngModelChange)=\"onValueChange($event)\"\n [disabled]=\"true\">\n {{label()}}\n </mat-checkbox>\n </span>\n } @else {\n <mat-checkbox \n [ngModel]=\"currentValue()\" \n (ngModelChange)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n [disabled]=\"!isEditable() || !isActive()\">\n {{label()}}\n </mat-checkbox>\n }\n</div>\n", styles: [":host{display:block;height:100%;width:100%}.checkbox-container{display:flex;align-items:center;justify-content:center;height:100%;width:100%;padding:4px;cursor:default}.checkbox-container.checkbox-display-editable{cursor:pointer}.checkbox-container.checkbox-display-editable:hover{background-color:#0000000a}.checkbox-container.checkbox-active{cursor:default}.checkbox-drillable{cursor:pointer;color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease}\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: MatCheckboxModule }, { kind: "component", type: i2$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
6169
6211
|
}
|
|
6170
6212
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: CheckboxComponent, decorators: [{
|
|
6171
6213
|
type: Component,
|
|
@@ -6408,7 +6450,7 @@ class DateComponent {
|
|
|
6408
6450
|
return '';
|
|
6409
6451
|
}
|
|
6410
6452
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6411
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: DateComponent, isStandalone: true, selector: "eru-date", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", dateChange: "dateChange", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, providers: [MatDatepickerModule, MatNativeDateModule], viewQueries: [{ propertyName: "datepicker", first: true, predicate: ["picker"], descendants: true }], ngImport: i0, template: "@if(isActive()){\n <mat-form-field appearance=\"outline\" class=\"date-form-field\">\n <input type=\"text\"\n matInput \n [matDatepicker]=\"picker\"\n appCustomDatePicker\n class=\"date-input\"\n [ngModel]=\"currentValue()\"\n [matDatepickerFilter]=\"dayFilter()\"\n (dateChange)=\"onDateChange($event.value)\"\n (click)=\"picker.open()\"\n readonly>\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n} @else {\n <div class=\"date-display\" \n [class.date-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"date-drillable\" (click)=\"onDrillableClick($event)\">{{getDisplayValue()}}</span>\n } @else {\n {{getDisplayValue()}}\n }\n </div>\n}\n", styles: [":host{display:block;height:100%;width:100%;position:relative;overflow:hidden!important}.date-form-field{width:100%!important;height:100%!important;padding:0!important;margin:0!important}.date-form-field .mat-mdc-form-field-subscript-wrapper{display:none!important}.date-form-field .mat-mdc-form-field-wrapper{width:100%!important;height:100%!important;padding:0!important;margin:0!important}.date-form-field .mat-mdc-form-field-wrapper .mat-mdc-form-field-flex{width:100%!important;height:100%!important;padding:0!important;margin:0!important;align-items:center;min-height:32px}.date-form-field .mat-mdc-form-field-wrapper .mat-mdc-form-field-flex .mat-mdc-form-field-infix{width:100%!important;height:100%!important;padding:0!important;margin:0!important;min-height:auto!important;border-top:none!important}.date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#00000061;border-width:1px}.date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing,.date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:var(--grid-primary, #6750a4)!important;border-width:2px!important}.date-input{width:100%!important;height:100%!important;padding:4px 8px!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;font-family:var(--grid-font-family, \"Poppins\")!important;color:var(--grid-on-surface, #1d1b20)!important;cursor:pointer!important;line-height:normal!important;box-sizing:border-box!important}.date-display{width:100%!important;height:100%!important;min-height:20px!important;display:block!important;padding:4px 8px!important;font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;color:var(--grid-on-surface, #1d1b20)!important;background:transparent!important;border:none!important;outline:none!important;text-overflow:ellipsis!important;overflow:hidden!important;white-space:nowrap!important;max-width:100%!important;box-sizing:border-box!important;line-height:1.4!important}.date-display-editable{cursor:pointer!important}.date-drillable{color:var(--grid-primary, #6750a4);text-decoration:underline;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4$
|
|
6453
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: DateComponent, isStandalone: true, selector: "eru-date", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", dateChange: "dateChange", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, providers: [MatDatepickerModule, MatNativeDateModule], viewQueries: [{ propertyName: "datepicker", first: true, predicate: ["picker"], descendants: true }], ngImport: i0, template: "@if(isActive()){\n <mat-form-field appearance=\"outline\" class=\"date-form-field\">\n <input type=\"text\"\n matInput \n [matDatepicker]=\"picker\"\n appCustomDatePicker\n class=\"date-input\"\n [ngModel]=\"currentValue()\"\n [matDatepickerFilter]=\"dayFilter()\"\n (dateChange)=\"onDateChange($event.value)\"\n (click)=\"picker.open()\"\n readonly>\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n} @else {\n <div class=\"date-display\" \n [class.date-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"date-drillable\" (click)=\"onDrillableClick($event)\">{{getDisplayValue()}}</span>\n } @else {\n {{getDisplayValue()}}\n }\n </div>\n}\n", styles: [":host{display:block;height:100%;width:100%;position:relative;overflow:hidden!important}.date-form-field{width:100%!important;height:100%!important;padding:0!important;margin:0!important}.date-form-field .mat-mdc-form-field-subscript-wrapper{display:none!important}.date-form-field .mat-mdc-form-field-wrapper{width:100%!important;height:100%!important;padding:0!important;margin:0!important}.date-form-field .mat-mdc-form-field-wrapper .mat-mdc-form-field-flex{width:100%!important;height:100%!important;padding:0!important;margin:0!important;align-items:center;min-height:32px}.date-form-field .mat-mdc-form-field-wrapper .mat-mdc-form-field-flex .mat-mdc-form-field-infix{width:100%!important;height:100%!important;padding:0!important;margin:0!important;min-height:auto!important;border-top:none!important}.date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#00000061;border-width:1px}.date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing,.date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:var(--grid-primary, #6750a4)!important;border-width:2px!important}.date-input{width:100%!important;height:100%!important;padding:4px 8px!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;font-family:var(--grid-font-family, \"Poppins\")!important;color:var(--grid-on-surface, #1d1b20)!important;cursor:pointer!important;line-height:normal!important;box-sizing:border-box!important}.date-display{width:100%!important;height:100%!important;min-height:20px!important;display:block!important;padding:4px 8px!important;font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;color:var(--grid-on-surface, #1d1b20)!important;background:transparent!important;border:none!important;outline:none!important;text-overflow:ellipsis!important;overflow:hidden!important;white-space:nowrap!important;max-width:100%!important;box-sizing:border-box!important;line-height:1.4!important}.date-display-editable{cursor:pointer!important}.date-drillable{color:var(--grid-primary, #6750a4);text-decoration:underline;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i4$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4$1.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "directive", type: CustomDatePickerDirective, selector: "[appCustomDatePicker]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
6412
6454
|
}
|
|
6413
6455
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DateComponent, decorators: [{
|
|
6414
6456
|
type: Component,
|
|
@@ -6489,7 +6531,7 @@ class TimePickerPanelComponent {
|
|
|
6489
6531
|
return String(num).padStart(2, '0');
|
|
6490
6532
|
}
|
|
6491
6533
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: TimePickerPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6492
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: TimePickerPanelComponent, isStandalone: true, selector: "eru-time-picker-panel", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, hour: { classPropertyName: "hour", publicName: "hour", isSignal: true, isRequired: false, transformFunction: null }, minute: { classPropertyName: "minute", publicName: "minute", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timeSelected: "timeSelected", close: "close" }, ngImport: i0, template: "<div class=\"time-picker-panel\">\n <div class=\"time-picker-header\">\n <span class=\"time-picker-title\">Select Time</span>\n <button mat-icon-button class=\"close-button\" (click)=\"onClose()\" type=\"button\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n \n <div class=\"time-picker-content\">\n <div class=\"time-column\">\n <div class=\"time-column-header\">Hour</div>\n <div class=\"time-scroll-container\">\n @for (hour of hours; track hour) {\n <button\n type=\"button\"\n class=\"time-option\"\n [class.selected]=\"isHourSelected(hour)\"\n (click)=\"onHourSelect(hour)\">\n {{formatNumber(hour)}}\n </button>\n }\n </div>\n </div>\n \n <div class=\"time-column\">\n <div class=\"time-column-header\">Minute</div>\n <div class=\"time-scroll-container\">\n @for (minute of minutes; track minute) {\n <button\n type=\"button\"\n class=\"time-option\"\n [class.selected]=\"isMinuteSelected(minute)\"\n (click)=\"onMinuteSelect(minute)\">\n {{formatNumber(minute)}}\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n\n", styles: [".time-picker-panel{background:#fff;border:1px solid rgba(0,0,0,.12);border-radius:4px;box-shadow:0 2px 8px #00000026;min-width:200px;max-width:300px;display:flex;flex-direction:column;overflow:hidden}.time-picker-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid rgba(0,0,0,.12);background-color:#00000005}.time-picker-title{font-size:14px;font-weight:500;color:#000000de}.close-button{width:32px;height:32px;line-height:32px}.close-button mat-icon{font-size:18px;width:18px;height:18px}.time-picker-content{display:flex;max-height:300px;overflow:hidden}.time-column{flex:1;display:flex;flex-direction:column;border-right:1px solid rgba(0,0,0,.12)}.time-column:last-child{border-right:none}.time-column-header{padding:8px 12px;font-size:12px;font-weight:500;color:#0009;text-align:center;background-color:#00000005;border-bottom:1px solid rgba(0,0,0,.12)}.time-scroll-container{flex:1;overflow-y:auto;padding:4px 0}.time-scroll-container::-webkit-scrollbar{width:6px}.time-scroll-container::-webkit-scrollbar-track{background:transparent}.time-scroll-container::-webkit-scrollbar-thumb{background:#0003;border-radius:3px}.time-scroll-container::-webkit-scrollbar-thumb:hover{background:#0000004d}.time-option{width:100%;padding:8px 12px;border:none;background:transparent;cursor:pointer;font-size:14px;color:#000000de;text-align:center;transition:background-color .2s ease}.time-option:hover{background-color:#0000000a}.time-option.selected{background-color:var(--grid-primary, #6750a4);color:#fff;font-weight:500}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$
|
|
6534
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: TimePickerPanelComponent, isStandalone: true, selector: "eru-time-picker-panel", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, hour: { classPropertyName: "hour", publicName: "hour", isSignal: true, isRequired: false, transformFunction: null }, minute: { classPropertyName: "minute", publicName: "minute", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { timeSelected: "timeSelected", close: "close" }, ngImport: i0, template: "<div class=\"time-picker-panel\">\n <div class=\"time-picker-header\">\n <span class=\"time-picker-title\">Select Time</span>\n <button mat-icon-button class=\"close-button\" (click)=\"onClose()\" type=\"button\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n \n <div class=\"time-picker-content\">\n <div class=\"time-column\">\n <div class=\"time-column-header\">Hour</div>\n <div class=\"time-scroll-container\">\n @for (hour of hours; track hour) {\n <button\n type=\"button\"\n class=\"time-option\"\n [class.selected]=\"isHourSelected(hour)\"\n (click)=\"onHourSelect(hour)\">\n {{formatNumber(hour)}}\n </button>\n }\n </div>\n </div>\n \n <div class=\"time-column\">\n <div class=\"time-column-header\">Minute</div>\n <div class=\"time-scroll-container\">\n @for (minute of minutes; track minute) {\n <button\n type=\"button\"\n class=\"time-option\"\n [class.selected]=\"isMinuteSelected(minute)\"\n (click)=\"onMinuteSelect(minute)\">\n {{formatNumber(minute)}}\n </button>\n }\n </div>\n </div>\n </div>\n</div>\n\n", styles: [".time-picker-panel{background:#fff;border:1px solid rgba(0,0,0,.12);border-radius:4px;box-shadow:0 2px 8px #00000026;min-width:200px;max-width:300px;display:flex;flex-direction:column;overflow:hidden}.time-picker-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid rgba(0,0,0,.12);background-color:#00000005}.time-picker-title{font-size:14px;font-weight:500;color:#000000de}.close-button{width:32px;height:32px;line-height:32px}.close-button mat-icon{font-size:18px;width:18px;height:18px}.time-picker-content{display:flex;max-height:300px;overflow:hidden}.time-column{flex:1;display:flex;flex-direction:column;border-right:1px solid rgba(0,0,0,.12)}.time-column:last-child{border-right:none}.time-column-header{padding:8px 12px;font-size:12px;font-weight:500;color:#0009;text-align:center;background-color:#00000005;border-bottom:1px solid rgba(0,0,0,.12)}.time-scroll-container{flex:1;overflow-y:auto;padding:4px 0}.time-scroll-container::-webkit-scrollbar{width:6px}.time-scroll-container::-webkit-scrollbar-track{background:transparent}.time-scroll-container::-webkit-scrollbar-thumb{background:#0003;border-radius:3px}.time-scroll-container::-webkit-scrollbar-thumb:hover{background:#0000004d}.time-option{width:100%;padding:8px 12px;border:none;background:transparent;cursor:pointer;font-size:14px;color:#000000de;text-align:center;transition:background-color .2s ease}.time-option:hover{background-color:#0000000a}.time-option.selected{background-color:var(--grid-primary, #6750a4);color:#fff;font-weight:500}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
6493
6535
|
}
|
|
6494
6536
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: TimePickerPanelComponent, decorators: [{
|
|
6495
6537
|
type: Component,
|
|
@@ -6549,7 +6591,7 @@ class TimePickerComponent {
|
|
|
6549
6591
|
event.stopPropagation();
|
|
6550
6592
|
}
|
|
6551
6593
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: TimePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6552
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: TimePickerComponent, isStandalone: true, selector: "eru-time-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "timeInput", first: true, predicate: ["timeInput"], descendants: true }], ngImport: i0, template: "<div class=\"time-picker-container\" (click)=\"$event.stopPropagation()\">\n <mat-form-field appearance=\"outline\" class=\"time-picker-field\">\n @if (label()) {\n <mat-label>{{label()}}</mat-label>\n }\n <input \n matInput \n type=\"text\"\n #timeInput\n [value]=\"value()\" \n (click)=\"onInputClick($event)\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n readonly>\n <mat-icon matSuffix (click)=\"onIconClick($event)\" class=\"time-picker-icon\">access_time</mat-icon>\n </mat-form-field>\n\n <ng-template \n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"timeInput\"\n [cdkConnectedOverlayOpen]=\"isPanelOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'time-picker-backdrop'\"\n (backdropClick)=\"onOverlayBackdropClick($event)\">\n <div \n class=\"time-picker-overlay\" \n (click)=\"onOverlayClick($event)\"\n (mousedown)=\"onOverlayClick($event)\">\n <eru-time-picker-panel\n [value]=\"value()\"\n (timeSelected)=\"onTimeSelected($event)\"\n (close)=\"onPanelClose()\">\n </eru-time-picker-panel>\n </div>\n </ng-template>\n</div>\n\n", styles: [":host{display:block;width:100%}.time-picker-container{width:100%;position:relative}.time-picker-field{width:100%}.time-picker-field .mat-mdc-form-field-subscript-wrapper{display:none}.time-picker-field input[type=text]{cursor:pointer}.time-picker-field .time-picker-icon{cursor:pointer;pointer-events:auto;-webkit-user-select:none;user-select:none;font-size:14px!important;width:14px!important;height:14px!important;line-height:14px!important;display:inline-flex;align-items:center;justify-content:center}.time-picker-field .time-picker-icon:hover{color:var(--grid-primary, #6750a4)}.time-picker-backdrop{background:transparent;pointer-events:auto}.time-picker-overlay{position:relative;z-index:1001;pointer-events:auto}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$
|
|
6594
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: TimePickerComponent, isStandalone: true, selector: "eru-time-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, viewQueries: [{ propertyName: "timeInput", first: true, predicate: ["timeInput"], descendants: true }], ngImport: i0, template: "<div class=\"time-picker-container\" (click)=\"$event.stopPropagation()\">\n <mat-form-field appearance=\"outline\" class=\"time-picker-field\">\n @if (label()) {\n <mat-label>{{label()}}</mat-label>\n }\n <input \n matInput \n type=\"text\"\n #timeInput\n [value]=\"value()\" \n (click)=\"onInputClick($event)\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n readonly>\n <mat-icon matSuffix (click)=\"onIconClick($event)\" class=\"time-picker-icon\">access_time</mat-icon>\n </mat-form-field>\n\n <ng-template \n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"timeInput\"\n [cdkConnectedOverlayOpen]=\"isPanelOpen()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'time-picker-backdrop'\"\n (backdropClick)=\"onOverlayBackdropClick($event)\">\n <div \n class=\"time-picker-overlay\" \n (click)=\"onOverlayClick($event)\"\n (mousedown)=\"onOverlayClick($event)\">\n <eru-time-picker-panel\n [value]=\"value()\"\n (timeSelected)=\"onTimeSelected($event)\"\n (close)=\"onPanelClose()\">\n </eru-time-picker-panel>\n </div>\n </ng-template>\n</div>\n\n", styles: [":host{display:block;width:100%}.time-picker-container{width:100%;position:relative}.time-picker-field{width:100%}.time-picker-field .mat-mdc-form-field-subscript-wrapper{display:none}.time-picker-field input[type=text]{cursor:pointer}.time-picker-field .time-picker-icon{cursor:pointer;pointer-events:auto;-webkit-user-select:none;user-select:none;font-size:14px!important;width:14px!important;height:14px!important;line-height:14px!important;display:inline-flex;align-items:center;justify-content:center}.time-picker-field .time-picker-icon:hover{color:var(--grid-primary, #6750a4)}.time-picker-backdrop{background:transparent;pointer-events:auto}.time-picker-overlay{position:relative;z-index:1001;pointer-events:auto}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$3.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "component", type: TimePickerPanelComponent, selector: "eru-time-picker-panel", inputs: ["value", "hour", "minute"], outputs: ["timeSelected", "close"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
6553
6595
|
}
|
|
6554
6596
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: TimePickerComponent, decorators: [{
|
|
6555
6597
|
type: Component,
|
|
@@ -6761,7 +6803,7 @@ class DatetimeComponent {
|
|
|
6761
6803
|
return '';
|
|
6762
6804
|
}
|
|
6763
6805
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DatetimeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6764
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: DatetimeComponent, isStandalone: true, selector: "eru-datetime", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", datetimeChange: "datetimeChange", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, providers: [MatDatepickerModule, MatNativeDateModule], viewQueries: [{ propertyName: "datepicker", first: true, predicate: ["picker"], descendants: true }], ngImport: i0, template: "@if(isActive()){\n <div class=\"datetime-input-container\">\n <mat-form-field appearance=\"outline\" class=\"datetime-date-form-field\">\n <input type=\"text\"\n matInput \n [matDatepicker]=\"picker\" \n appCustomDatePicker\n class=\"datetime-date-input\" \n [ngModel]=\"selectedDate()\"\n (dateChange)=\"onDateChange($event.value)\" \n (click)=\"picker.open()\" \n readonly>\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n <eru-time-picker\n [value]=\"selectedTime()\"\n (valueChange)=\"onTimeChange($event)\"\n class=\"datetime-time-picker\">\n </eru-time-picker>\n </div>\n} @else {\n <div class=\"datetime-display\" \n [class.datetime-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"datetime-drillable\" (click)=\"onDrillableClick($event)\">{{getDisplayValue()}}</span>\n } @else {\n {{getDisplayValue()}}\n }\n </div>\n}\n\n", styles: [":host{display:block;height:100%;width:100%;position:relative;overflow:hidden!important}.datetime-input-container{display:flex;align-items:center;gap:8px;width:100%;height:100%;padding:4px 8px;box-sizing:border-box}.datetime-date-form-field{flex:2;min-width:0;max-width:50%;height:100%;padding:0!important;margin:0!important}.datetime-date-form-field .mat-mdc-form-field-subscript-wrapper{display:none!important}.datetime-date-form-field .mat-mdc-form-field-wrapper{width:100%!important;height:100%!important;padding:0!important;margin:0!important}.datetime-date-form-field .mat-mdc-form-field-wrapper .mat-mdc-form-field-flex{width:100%!important;height:100%!important;padding:0!important;margin:0!important;align-items:center;min-height:32px}.datetime-date-form-field .mat-mdc-form-field-wrapper .mat-mdc-form-field-flex .mat-mdc-form-field-infix{width:100%!important;height:100%!important;padding:0!important;margin:0!important;min-height:auto!important;border-top:none!important}.datetime-date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.datetime-date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.datetime-date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#00000061;border-width:1px}.datetime-date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.datetime-date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.datetime-date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing,.datetime-date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.datetime-date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.datetime-date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:var(--grid-primary, #6750a4)!important;border-width:2px!important}.datetime-date-input{width:100%!important;height:100%!important;padding:4px 8px!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;font-family:var(--grid-font-family, \"Poppins\")!important;color:var(--grid-on-surface, #1d1b20)!important;cursor:pointer!important;line-height:normal!important;box-sizing:border-box!important}.datetime-time-picker{flex:1;min-width:0;max-width:50%}.datetime-time-picker .time-picker-field{margin:0}.datetime-time-picker .time-picker-field .mat-mdc-text-field-wrapper{padding-bottom:0}.datetime-time-picker .time-picker-field .mat-mdc-form-field-flex{align-items:center;min-height:32px}.datetime-time-picker .time-picker-field .mat-mdc-form-field-infix{padding:0;border:none;min-height:32px}.datetime-time-picker .time-picker-field input{font-size:14px;padding:4px 8px}.datetime-display{width:100%!important;height:100%!important;min-height:20px!important;display:block!important;padding:4px 8px!important;font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;color:var(--grid-on-surface, #1d1b20)!important;background:transparent!important;border:none!important;outline:none!important;text-overflow:ellipsis!important;overflow:hidden!important;white-space:nowrap!important;max-width:100%!important;box-sizing:border-box!important;line-height:1.4!important}.datetime-display-editable{cursor:pointer!important}.datetime-drillable{color:var(--grid-primary, #6750a4);text-decoration:underline;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4$
|
|
6806
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: DatetimeComponent, isStandalone: true, selector: "eru-datetime", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", datetimeChange: "datetimeChange", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, providers: [MatDatepickerModule, MatNativeDateModule], viewQueries: [{ propertyName: "datepicker", first: true, predicate: ["picker"], descendants: true }], ngImport: i0, template: "@if(isActive()){\n <div class=\"datetime-input-container\">\n <mat-form-field appearance=\"outline\" class=\"datetime-date-form-field\">\n <input type=\"text\"\n matInput \n [matDatepicker]=\"picker\" \n appCustomDatePicker\n class=\"datetime-date-input\" \n [ngModel]=\"selectedDate()\"\n (dateChange)=\"onDateChange($event.value)\" \n (click)=\"picker.open()\" \n readonly>\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\n <mat-datepicker #picker></mat-datepicker>\n </mat-form-field>\n <eru-time-picker\n [value]=\"selectedTime()\"\n (valueChange)=\"onTimeChange($event)\"\n class=\"datetime-time-picker\">\n </eru-time-picker>\n </div>\n} @else {\n <div class=\"datetime-display\" \n [class.datetime-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"datetime-drillable\" (click)=\"onDrillableClick($event)\">{{getDisplayValue()}}</span>\n } @else {\n {{getDisplayValue()}}\n }\n </div>\n}\n\n", styles: [":host{display:block;height:100%;width:100%;position:relative;overflow:hidden!important}.datetime-input-container{display:flex;align-items:center;gap:8px;width:100%;height:100%;padding:4px 8px;box-sizing:border-box}.datetime-date-form-field{flex:2;min-width:0;max-width:50%;height:100%;padding:0!important;margin:0!important}.datetime-date-form-field .mat-mdc-form-field-subscript-wrapper{display:none!important}.datetime-date-form-field .mat-mdc-form-field-wrapper{width:100%!important;height:100%!important;padding:0!important;margin:0!important}.datetime-date-form-field .mat-mdc-form-field-wrapper .mat-mdc-form-field-flex{width:100%!important;height:100%!important;padding:0!important;margin:0!important;align-items:center;min-height:32px}.datetime-date-form-field .mat-mdc-form-field-wrapper .mat-mdc-form-field-flex .mat-mdc-form-field-infix{width:100%!important;height:100%!important;padding:0!important;margin:0!important;min-height:auto!important;border-top:none!important}.datetime-date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.datetime-date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.datetime-date-form-field .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:#00000061;border-width:1px}.datetime-date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.datetime-date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.datetime-date-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing,.datetime-date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.datetime-date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.datetime-date-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:var(--grid-primary, #6750a4)!important;border-width:2px!important}.datetime-date-input{width:100%!important;height:100%!important;padding:4px 8px!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;font-family:var(--grid-font-family, \"Poppins\")!important;color:var(--grid-on-surface, #1d1b20)!important;cursor:pointer!important;line-height:normal!important;box-sizing:border-box!important}.datetime-time-picker{flex:1;min-width:0;max-width:50%}.datetime-time-picker .time-picker-field{margin:0}.datetime-time-picker .time-picker-field .mat-mdc-text-field-wrapper{padding-bottom:0}.datetime-time-picker .time-picker-field .mat-mdc-form-field-flex{align-items:center;min-height:32px}.datetime-time-picker .time-picker-field .mat-mdc-form-field-infix{padding:0;border:none;min-height:32px}.datetime-time-picker .time-picker-field input{font-size:14px;padding:4px 8px}.datetime-display{width:100%!important;height:100%!important;min-height:20px!important;display:block!important;padding:4px 8px!important;font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;color:var(--grid-on-surface, #1d1b20)!important;background:transparent!important;border:none!important;outline:none!important;text-overflow:ellipsis!important;overflow:hidden!important;white-space:nowrap!important;max-width:100%!important;box-sizing:border-box!important;line-height:1.4!important}.datetime-display-editable{cursor:pointer!important}.datetime-drillable{color:var(--grid-primary, #6750a4);text-decoration:underline;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i4$1.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i4$1.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i4$1.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "ngmodule", type: MatNativeDateModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "directive", type: CustomDatePickerDirective, selector: "[appCustomDatePicker]" }, { kind: "component", type: TimePickerComponent, selector: "eru-time-picker", inputs: ["value", "label", "placeholder", "disabled"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
6765
6807
|
}
|
|
6766
6808
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DatetimeComponent, decorators: [{
|
|
6767
6809
|
type: Component,
|
|
@@ -6975,7 +7017,7 @@ class DurationComponent {
|
|
|
6975
7017
|
return num < 10 ? `0${num}` : `${num}`;
|
|
6976
7018
|
}
|
|
6977
7019
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DurationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6978
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: DurationComponent, isStandalone: true, selector: "eru-duration", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, ngImport: i0, template: "<div class=\"duration-overlay-container\">\n <div \n class=\"duration-cell-wrapper\"\n cdkOverlayOrigin \n #durationTrigger=\"cdkOverlayOrigin\"\n [class.duration-display-editable]=\"isEditable() && !isActive()\"\n (dblclick)=\"onActivate()\">\n <div class=\"duration-display\">\n @if (isDrillable() && !isActive()) {\n <span class=\"duration-drillable\" (click)=\"onDrillableClick($event)\">{{getDisplayValue()}}</span>\n } @else {\n {{getDisplayValue()}}\n }\n </div>\n </div>\n\n <ng-template \n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"durationTrigger\"\n [cdkConnectedOverlayOpen]=\"isOverlayOpen() && isActive()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'duration-backdrop'\"\n (backdropClick)=\"onOverlayBackdropClick()\">\n <div \n class=\"duration-editor\" \n (click)=\"onOverlayClick($event)\">\n <mat-tab-group \n [selectedIndex]=\"selectedTab()\" \n (selectedIndexChange)=\"onTabChange($event)\"\n class=\"duration-tabs\">\n <mat-tab label=\"Manual\">\n <div class=\"duration-tab-content\">\n <mat-form-field appearance=\"outline\" class=\"duration-input-field\">\n <mat-label>Minutes</mat-label>\n <input \n matInput \n type=\"number\" \n [ngModel]=\"manualMinutes()\" \n (ngModelChange)=\"onManualMinutesChange($event)\"\n [placeholder]=\"placeholder()\"\n min=\"0\">\n </mat-form-field>\n <div class=\"duration-preview\">\n {{formatDuration(manualMinutes())}}\n </div>\n </div>\n </mat-tab>\n \n <mat-tab label=\"Range\">\n <div class=\"duration-tab-content\">\n <div class=\"time-range-container\" (click)=\"$event.stopPropagation()\">\n <eru-time-picker\n [value]=\"startTime()\"\n [label]=\"'Start Time'\"\n (valueChange)=\"onStartTimeChange($event)\"\n class=\"time-picker-wrapper\">\n </eru-time-picker>\n \n <span class=\"time-separator\">-</span>\n \n <eru-time-picker\n [value]=\"endTime()\"\n [label]=\"'End Time'\"\n (valueChange)=\"onEndTimeChange($event)\"\n class=\"time-picker-wrapper\">\n </eru-time-picker>\n </div>\n <div class=\"duration-preview\">\n Duration: {{formatDuration(manualMinutes())}}\n </div>\n </div>\n </mat-tab>\n </mat-tab-group>\n </div>\n </ng-template>\n</div>\n\n", styles: [":host{display:block;height:100%;width:100%}.duration-overlay-container{width:100%;height:100%}.duration-cell-wrapper{display:flex;align-items:center;justify-content:flex-start;height:100%;width:100%;padding:4px 8px;cursor:default}.duration-cell-wrapper.duration-display-editable{cursor:pointer}.duration-cell-wrapper.duration-display-editable:hover{background-color:#0000000a}.duration-display{display:flex;align-items:center;justify-content:flex-start;width:100%;height:100%}.duration-drillable{cursor:pointer;color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease}.duration-drillable:hover{color:var(--grid-primary, #6750a4);opacity:.8}.duration-backdrop{background:transparent}.duration-editor{background:#fff;border:1px solid rgba(0,0,0,.12);border-radius:4px;box-shadow:0 2px 8px #00000026;min-width:300px;padding:16px;position:relative;z-index:1000}.duration-tabs{margin-bottom:16px}.duration-tabs .mat-mdc-tab-header{border-bottom:1px solid rgba(0,0,0,.12)}.duration-tabs .mat-mdc-tab-label{min-width:80px}.duration-tab-content{padding:16px 0 8px;display:flex;flex-direction:column;gap:16px}.duration-input-field{width:100%}.duration-input-field .mat-mdc-form-field-subscript-wrapper{display:none}.time-range-container{display:flex;align-items:center;gap:12px;width:100%}.time-picker-wrapper{flex:1;min-width:0}.time-separator{font-size:18px;font-weight:500;color:#0009;flex-shrink:0}.duration-preview{padding:8px 12px;background-color:#0000000a;border-radius:4px;font-size:var(--grid-font-size-body, 12px);font-weight:500;color:#000000de;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i4$
|
|
7020
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: DurationComponent, isStandalone: true, selector: "eru-duration", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, ngImport: i0, template: "<div class=\"duration-overlay-container\">\n <div \n class=\"duration-cell-wrapper\"\n cdkOverlayOrigin \n #durationTrigger=\"cdkOverlayOrigin\"\n [class.duration-display-editable]=\"isEditable() && !isActive()\"\n (dblclick)=\"onActivate()\">\n <div class=\"duration-display\">\n @if (isDrillable() && !isActive()) {\n <span class=\"duration-drillable\" (click)=\"onDrillableClick($event)\">{{getDisplayValue()}}</span>\n } @else {\n {{getDisplayValue()}}\n }\n </div>\n </div>\n\n <ng-template \n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"durationTrigger\"\n [cdkConnectedOverlayOpen]=\"isOverlayOpen() && isActive()\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'duration-backdrop'\"\n (backdropClick)=\"onOverlayBackdropClick()\">\n <div \n class=\"duration-editor\" \n (click)=\"onOverlayClick($event)\">\n <mat-tab-group \n [selectedIndex]=\"selectedTab()\" \n (selectedIndexChange)=\"onTabChange($event)\"\n class=\"duration-tabs\">\n <mat-tab label=\"Manual\">\n <div class=\"duration-tab-content\">\n <mat-form-field appearance=\"outline\" class=\"duration-input-field\">\n <mat-label>Minutes</mat-label>\n <input \n matInput \n type=\"number\" \n [ngModel]=\"manualMinutes()\" \n (ngModelChange)=\"onManualMinutesChange($event)\"\n [placeholder]=\"placeholder()\"\n min=\"0\">\n </mat-form-field>\n <div class=\"duration-preview\">\n {{formatDuration(manualMinutes())}}\n </div>\n </div>\n </mat-tab>\n \n <mat-tab label=\"Range\">\n <div class=\"duration-tab-content\">\n <div class=\"time-range-container\" (click)=\"$event.stopPropagation()\">\n <eru-time-picker\n [value]=\"startTime()\"\n [label]=\"'Start Time'\"\n (valueChange)=\"onStartTimeChange($event)\"\n class=\"time-picker-wrapper\">\n </eru-time-picker>\n \n <span class=\"time-separator\">-</span>\n \n <eru-time-picker\n [value]=\"endTime()\"\n [label]=\"'End Time'\"\n (valueChange)=\"onEndTimeChange($event)\"\n class=\"time-picker-wrapper\">\n </eru-time-picker>\n </div>\n <div class=\"duration-preview\">\n Duration: {{formatDuration(manualMinutes())}}\n </div>\n </div>\n </mat-tab>\n </mat-tab-group>\n </div>\n </ng-template>\n</div>\n\n", styles: [":host{display:block;height:100%;width:100%}.duration-overlay-container{width:100%;height:100%}.duration-cell-wrapper{display:flex;align-items:center;justify-content:flex-start;height:100%;width:100%;padding:4px 8px;cursor:default}.duration-cell-wrapper.duration-display-editable{cursor:pointer}.duration-cell-wrapper.duration-display-editable:hover{background-color:#0000000a}.duration-display{display:flex;align-items:center;justify-content:flex-start;width:100%;height:100%}.duration-drillable{cursor:pointer;color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease}.duration-drillable:hover{color:var(--grid-primary, #6750a4);opacity:.8}.duration-backdrop{background:transparent}.duration-editor{background:#fff;border:1px solid rgba(0,0,0,.12);border-radius:4px;box-shadow:0 2px 8px #00000026;min-width:300px;padding:16px;position:relative;z-index:1000}.duration-tabs{margin-bottom:16px}.duration-tabs .mat-mdc-tab-header{border-bottom:1px solid rgba(0,0,0,.12)}.duration-tabs .mat-mdc-tab-label{min-width:80px}.duration-tab-content{padding:16px 0 8px;display:flex;flex-direction:column;gap:16px}.duration-input-field{width:100%}.duration-input-field .mat-mdc-form-field-subscript-wrapper{display:none}.time-range-container{display:flex;align-items:center;gap:12px;width:100%}.time-picker-wrapper{flex:1;min-width:0}.time-separator{font-size:18px;font-weight:500;color:#0009;flex-shrink:0}.duration-preview{padding:8px 12px;background-color:#0000000a;border-radius:4px;font-size:var(--grid-font-size-body, 12px);font-weight:500;color:#000000de;text-align:center}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i4$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$3.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$3.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: TimePickerComponent, selector: "eru-time-picker", inputs: ["value", "label", "placeholder", "disabled"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
6979
7021
|
}
|
|
6980
7022
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: DurationComponent, decorators: [{
|
|
6981
7023
|
type: Component,
|
|
@@ -7317,7 +7359,7 @@ class PhoneComponent {
|
|
|
7317
7359
|
}
|
|
7318
7360
|
}
|
|
7319
7361
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: PhoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7320
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: PhoneComponent, isStandalone: true, selector: "eru-phone", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, defaultCountry: { classPropertyName: "defaultCountry", publicName: "defaultCountry", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "phoneContainer", first: true, predicate: ["phoneContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n <mat-form-field\n appearance=\"outline\"\n class=\"phone-form-field\"\n [class.phone-form-field-focused]=\"isFocused()\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div class=\"phone-input-container\" #phoneContainer>\n <mat-select\n class=\"country-select\"\n panelClass=\"country-select-panel\"\n [value]=\"selectedCountry().code\"\n [disabled]=\"!isEditable()\"\n (selectionChange)=\"onCountryChange($event.value)\"\n (openedChange)=\"onCountrySelectOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n <mat-select-trigger>\n <span class=\"country-option\">\n <span class=\"country-flag\">{{ displayFlag(selectedCountry()) }}</span>\n <span class=\"country-dial-code\">{{ selectedCountry().dial_code }}</span>\n </span>\n </mat-select-trigger>\n <mat-option disabled class=\"search-option\">\n <mat-form-field\n [appearance]=\"'outline'\"\n class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"search-input\"\n placeholder=\"filter options...\"\n [value]=\"countrySearchText()\"\n (input)=\"onCountrySearchChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n </mat-form-field>\n </mat-option>\n @for (country of filteredCountries(); track country.code) {\n <mat-option [value]=\"country.code\">\n <span class=\"country-option\">\n <span class=\"country-flag\">{{ displayFlag(country) }}</span>\n <span class=\"country-dial-code\">{{ country.dial_code }}</span>\n </span>\n </mat-option>\n }\n </mat-select>\n <input\n matInput\n type=\"tel\"\n class=\"phone-input\"\n placeholder=\"\"\n [value]=\"phoneNumber()\"\n (input)=\"onPhoneNumberInput($event)\"\n (focus)=\"onInputFocus($event)\"\n (blur)=\"onInputBlur($event)\"\n (click)=\"$event.stopPropagation()\">\n </div>\n </mat-form-field>\n} @else {\n <div class=\"phone-display\" \n [class.phone-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"phone-drillable\" (click)=\"onDrillableClick($event)\"><div class=\"phone-display-content\">\n <span class=\"phone-flag-display\">{{getDisplayFlag()}}</span> \n <span class=\"phone-number-display\">{{getDisplayPhoneNumber()}}</span>\n </div></span>\n } @else {\n <div class=\"phone-display-content\">\n <span class=\"phone-flag-display\">{{getDisplayFlag()}}</span> \n <span class=\"phone-number-display\">{{getDisplayPhoneNumber()}}</span>\n </div>\n }\n </div>\n}\n\n", styles: [":host{display:block;height:100%;width:100%}.phone-form-field{width:100%!important;height:100%!important;padding:2px!important;margin:0!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;line-height:normal!important;box-sizing:border-box!important;max-width:none!important;min-width:0!important;flex:none!important}.phone-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.phone-form-field.phone-form-field-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.phone-form-field.phone-form-field-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.phone-form-field.phone-form-field-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:var(--grid-primary, #6750a4)!important;border-width:2px!important}.phone-form-field.phone-form-field-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch{border-right:none!important;border-left:none!important}.phone-form-field.phone-form-field-focused .mat-mdc-form-field-focus-overlay{background-color:transparent!important}.phone-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.phone-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.phone-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing,.phone-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.phone-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.phone-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:var(--grid-primary, #6750a4)!important;border-width:2px!important}.phone-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.phone-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch{border-right:none!important;border-left:none!important}.phone-input-container{display:flex;align-items:center;gap:8px;width:100%}.country-select{min-width:60px;max-width:60px;width:60px}.country-option{display:flex;align-items:center;gap:2px}mat-option .country-option{display:flex;align-items:center}mat-option .country-option{display:flex!important;align-items:center!important;gap:8px!important}.country-flag{font-size:var(--grid-font-size-body, 12px)!important;display:inline-block;line-height:1;padding-left:2px;vertical-align:middle;font-family:var(--flag-font-stack)!important;unicode-bidi:isolate;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-feature-settings:normal;font-variant-emoji:emoji;isolation:isolate}.country-dial-code{font-weight:500}.phone-input{flex:1}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mdc-list-item__primary-text{opacity:1!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.search-input::placeholder{color:#0009}[dir=rtl] .search-input::placeholder{color:#0009}.phone-number-display{font-family:var(--grid-font-family, \"Poppins\")!important}.phone-display{width:100%!important;height:100%!important;min-height:20px!important;display:block!important;padding:4px 8px!important;font-family:var(--flag-font-stack, --grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;color:var(--grid-on-surface, #1d1b20)!important;background:transparent!important;border:none!important;outline:none!important;text-overflow:ellipsis!important;overflow:hidden!important;white-space:nowrap!important;max-width:100%!important;box-sizing:border-box!important;transition:background-color .2s ease!important;line-height:1.4!important;text-align:left!important}.phone-display>.phone-drillable{text-overflow:ellipsis!important;overflow:hidden!important;white-space:nowrap!important;max-width:100%!important;width:100%!important;display:block!important}.phone-display-content{display:flex!important;align-items:center!important;gap:4px!important;width:100%!important;overflow:hidden!important}.phone-display-content .phone-flag-display{flex-shrink:0!important;display:inline-block!important;font-size:var(--grid-font-size-body, 12px)!important;line-height:1!important;vertical-align:middle!important;font-family:var(--flag-font-stack)!important;unicode-bidi:isolate!important;text-rendering:optimizeLegibility!important;-webkit-font-smoothing:antialiased!important;-moz-osx-font-smoothing:grayscale!important;font-feature-settings:normal!important;font-variant-emoji:emoji!important;isolation:isolate!important}.phone-display-content .phone-number-display{flex:1!important;min-width:0!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;font-family:var(--grid-font-family, \"Poppins\")!important}.phone-display-editable{cursor:pointer!important}.phone-drillable{color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease;cursor:pointer;padding:4px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i2$2.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
7362
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: PhoneComponent, isStandalone: true, selector: "eru-phone", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, defaultCountry: { classPropertyName: "defaultCountry", publicName: "defaultCountry", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "phoneContainer", first: true, predicate: ["phoneContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n <mat-form-field\n appearance=\"outline\"\n class=\"phone-form-field\"\n [class.phone-form-field-focused]=\"isFocused()\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div class=\"phone-input-container\" #phoneContainer>\n <mat-select\n class=\"country-select\"\n panelClass=\"country-select-panel\"\n [value]=\"selectedCountry().code\"\n [disabled]=\"!isEditable()\"\n (selectionChange)=\"onCountryChange($event.value)\"\n (openedChange)=\"onCountrySelectOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n <mat-select-trigger>\n <span class=\"country-option\">\n <span class=\"country-flag\">{{ displayFlag(selectedCountry()) }}</span>\n <span class=\"country-dial-code\">{{ selectedCountry().dial_code }}</span>\n </span>\n </mat-select-trigger>\n <mat-option disabled class=\"search-option\">\n <mat-form-field\n [appearance]=\"'outline'\"\n class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"search-input\"\n placeholder=\"filter options...\"\n [value]=\"countrySearchText()\"\n (input)=\"onCountrySearchChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\">\n </mat-form-field>\n </mat-option>\n @for (country of filteredCountries(); track country.code) {\n <mat-option [value]=\"country.code\">\n <span class=\"country-option\">\n <span class=\"country-flag\">{{ displayFlag(country) }}</span>\n <span class=\"country-dial-code\">{{ country.dial_code }}</span>\n </span>\n </mat-option>\n }\n </mat-select>\n <input\n matInput\n type=\"tel\"\n class=\"phone-input\"\n placeholder=\"\"\n [value]=\"phoneNumber()\"\n (input)=\"onPhoneNumberInput($event)\"\n (focus)=\"onInputFocus($event)\"\n (blur)=\"onInputBlur($event)\"\n (click)=\"$event.stopPropagation()\">\n </div>\n </mat-form-field>\n} @else {\n <div class=\"phone-display\" \n [class.phone-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"phone-drillable\" (click)=\"onDrillableClick($event)\"><div class=\"phone-display-content\">\n <span class=\"phone-flag-display\">{{getDisplayFlag()}}</span> \n <span class=\"phone-number-display\">{{getDisplayPhoneNumber()}}</span>\n </div></span>\n } @else {\n <div class=\"phone-display-content\">\n <span class=\"phone-flag-display\">{{getDisplayFlag()}}</span> \n <span class=\"phone-number-display\">{{getDisplayPhoneNumber()}}</span>\n </div>\n }\n </div>\n}\n\n", styles: [":host{display:block;height:100%;width:100%}.phone-form-field{width:100%!important;height:100%!important;padding:2px!important;margin:0!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;line-height:normal!important;box-sizing:border-box!important;max-width:none!important;min-width:0!important;flex:none!important}.phone-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.phone-form-field.phone-form-field-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.phone-form-field.phone-form-field-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.phone-form-field.phone-form-field-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:var(--grid-primary, #6750a4)!important;border-width:2px!important}.phone-form-field.phone-form-field-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch{border-right:none!important;border-left:none!important}.phone-form-field.phone-form-field-focused .mat-mdc-form-field-focus-overlay{background-color:transparent!important}.phone-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.phone-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.phone-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing,.phone-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__leading,.phone-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.phone-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__trailing{border-color:var(--grid-primary, #6750a4)!important;border-width:2px!important}.phone-form-field.mat-focused .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch,.phone-form-field.mat-form-field-should-float .mat-mdc-text-field-wrapper .mdc-notched-outline .mdc-notched-outline__notch{border-right:none!important;border-left:none!important}.phone-input-container{display:flex;align-items:center;gap:8px;width:100%}.country-select{min-width:60px;max-width:60px;width:60px}.country-option{display:flex;align-items:center;gap:2px}mat-option .country-option{display:flex;align-items:center}mat-option .country-option{display:flex!important;align-items:center!important;gap:8px!important}.country-flag{font-size:var(--grid-font-size-body, 12px)!important;display:inline-block;line-height:1;padding-left:2px;vertical-align:middle;font-family:var(--flag-font-stack)!important;unicode-bidi:isolate;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-feature-settings:normal;font-variant-emoji:emoji;isolation:isolate}.country-dial-code{font-weight:500}.phone-input{flex:1}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mdc-list-item__primary-text{opacity:1!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.search-input::placeholder{color:#0009}[dir=rtl] .search-input::placeholder{color:#0009}.phone-number-display{font-family:var(--grid-font-family, \"Poppins\")!important}.phone-display{width:100%!important;height:100%!important;min-height:20px!important;display:block!important;padding:4px 8px!important;font-family:var(--flag-font-stack, --grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;color:var(--grid-on-surface, #1d1b20)!important;background:transparent!important;border:none!important;outline:none!important;text-overflow:ellipsis!important;overflow:hidden!important;white-space:nowrap!important;max-width:100%!important;box-sizing:border-box!important;transition:background-color .2s ease!important;line-height:1.4!important;text-align:left!important}.phone-display>.phone-drillable{text-overflow:ellipsis!important;overflow:hidden!important;white-space:nowrap!important;max-width:100%!important;width:100%!important;display:block!important}.phone-display-content{display:flex!important;align-items:center!important;gap:4px!important;width:100%!important;overflow:hidden!important}.phone-display-content .phone-flag-display{flex-shrink:0!important;display:inline-block!important;font-size:var(--grid-font-size-body, 12px)!important;line-height:1!important;vertical-align:middle!important;font-family:var(--flag-font-stack)!important;unicode-bidi:isolate!important;text-rendering:optimizeLegibility!important;-webkit-font-smoothing:antialiased!important;-moz-osx-font-smoothing:grayscale!important;font-feature-settings:normal!important;font-variant-emoji:emoji!important;isolation:isolate!important}.phone-display-content .phone-number-display{flex:1!important;min-width:0!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;font-family:var(--grid-font-family, \"Poppins\")!important}.phone-display-editable{cursor:pointer!important}.phone-drillable{color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease;cursor:pointer;padding:4px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i2$3.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
7321
7363
|
}
|
|
7322
7364
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: PhoneComponent, decorators: [{
|
|
7323
7365
|
type: Component,
|
|
@@ -7452,7 +7494,7 @@ class ProgressComponent {
|
|
|
7452
7494
|
return cfg[property];
|
|
7453
7495
|
}
|
|
7454
7496
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ProgressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7455
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ProgressComponent, isStandalone: true, selector: "eru-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, ngImport: i0, template: "@if (isActive()) {\n<div class=\"progress-input-container\"\n [style.--mat-slider-active-track-color]=\"barColor()\"\n [style.--mat-slider-disabled-active-track-color]=\"barColor()\"\n [style.--mat-slider-with-tick-marks-active-container-color]=\"barColor()\"\n [style.--mat-slider-handle-color]=\"barColor()\"\n [style.--mat-slider-focus-handle-color]=\"barColor()\"\n [style.--mat-slider-hover-handle-color]=\"barColor()\"\n [style.--mat-slider-disabled-handle-color]=\"barColor()\"\n [style.--mat-slider-ripple-color]=\"barColor()\"\n (dblclick)=\"onActivate(); $event.stopPropagation()\">\n <span class=\"progress-value\" [style.color]=\"barColor()\">{{valueLabel()}}</span>\n <!-- Only ever one of these on screen (the active cell), so it keeps the\n tick marks and the rest of its appearance exactly as before. -->\n <mat-slider\n class=\"progress-slider\"\n [min]=\"0\"\n [max]=\"100\"\n [step]=\"1\"\n [discrete]=\"true\"\n [showTickMarks]=\"true\"\n [disabled]=\"!isEditable()\">\n <input\n matSliderThumb\n [ngModel]=\"displayValue()\"\n (ngModelChange)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n [disabled]=\"!isEditable()\">\n </mat-slider>\n</div>\n} @else {\n<!-- Read-only: a plain track + fill rather than a disabled mat-slider.\n The slider mounted here even when the cell was not being edited, and with\n step=1 over 0-100 its tick marks alone were 101 DOM nodes per cell \u2014 on a\n 25-row grid that was 2,525 nodes and the single largest cost in rendering\n the table. It also read as interactive when it was not: the thumb invited\n a drag that did nothing. Double-click still activates, which mounts the\n real slider above. -->\n<div class=\"progress-view-container\" (dblclick)=\"onActivate(); $event.stopPropagation()\">\n <span class=\"progress-value\" [style.color]=\"barColor()\">{{valueLabel()}}</span>\n <div class=\"progress-view-track\">\n <div class=\"progress-view-fill\" [style.width.%]=\"displayValue()\"\n [style.background]=\"barColor()\"></div>\n </div>\n</div>\n}\n", styles: [":root{--mat-slider-with-overlap-handle-outline-color: var(--grid-primary, #6750a4) !important;--mat-slider-with-tick-marks-active-container-color: var(--grid-primary, #6750a4) !important;--mat-slider-handle-height: 12px;--mat-slider-handle-width: 12px;--mat-slider-disabled-active-track-color: var(--grid-primary, #6750a4);--mat-slider-active-track-color: var(--grid-primary, #6750a4)}:host{display:block;height:100%;width:100%}.progress-bar-container{width:100%;height:100%;min-height:30px;position:relative;background:#e0e0e0;border-radius:4px;cursor:pointer}.progress-bar{height:100%;background:var(--grid-primary, #6750a4);transition:width .3s;border-radius:4px}.progress-text{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:var(--grid-font-size-body, 12px);font-weight:500;color:var(--grid-on-surface, #1d1b20);pointer-events:none;z-index:1}.drillable-value{color:inherit;text-decoration:underline;cursor:pointer;pointer-events:auto}.drillable-value:hover{opacity:.8}.progress-input-container{display:flex;flex-direction:row-reverse;align-items:center;padding:4px;width:100%;box-sizing:border-box;overflow:visible;max-height:30px}.progress-input-container.disabled{cursor:pointer}.progress-input-container.disabled .progress-slider{pointer-events:none}.progress-view-container{display:flex;flex-direction:row-reverse;align-items:center;gap:8px;padding:4px;width:100%;box-sizing:border-box;max-height:30px;cursor:pointer}.progress-view-track{flex:1 1 0%;min-width:0;height:4px;border-radius:2px;background:var(--grid-surface-variant, #e0e0e0);overflow:hidden}.progress-view-fill{height:100%;border-radius:2px;background:var(--grid-primary, #6750a4);transition:width .3s}.progress-value{font-size:var(--grid-font-size-body, 12px);font-weight:500;color:var(--grid-on-surface, #1d1b20);flex:0 0 auto;min-width:35px;text-align:right;white-space:nowrap;flex-shrink:0}.progress-slider{flex:1 1 0%;min-width:0!important;max-width:100%!important;overflow:visible}.progress-slider .mdc-slider__track{left:0!important}.progress-slider .mdc-slider{padding-left:0!important;margin-left:0!important}.progress-slider .mdc-slider__value-indicator,.progress-slider .mdc-slider__value-indicator-container{display:none!important;visibility:hidden!important}.progress-slider .mdc-slider__thumb:before,.progress-slider .mdc-slider__thumb:after{display:none!important;content:none!important}.progress-slider .mdc-slider__thumb-knob:before,.progress-slider .mdc-slider__thumb-knob:after{display:none!important;content:none!important}.progress-slider [class*=value-indicator],.progress-slider [class*=tooltip]{display:none!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: MatSliderModule }, { kind: "component", type: i2$
|
|
7497
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ProgressComponent, isStandalone: true, selector: "eru-progress", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, ngImport: i0, template: "@if (isActive()) {\n<div class=\"progress-input-container\"\n [style.--mat-slider-active-track-color]=\"barColor()\"\n [style.--mat-slider-disabled-active-track-color]=\"barColor()\"\n [style.--mat-slider-with-tick-marks-active-container-color]=\"barColor()\"\n [style.--mat-slider-handle-color]=\"barColor()\"\n [style.--mat-slider-focus-handle-color]=\"barColor()\"\n [style.--mat-slider-hover-handle-color]=\"barColor()\"\n [style.--mat-slider-disabled-handle-color]=\"barColor()\"\n [style.--mat-slider-ripple-color]=\"barColor()\"\n (dblclick)=\"onActivate(); $event.stopPropagation()\">\n <span class=\"progress-value\" [style.color]=\"barColor()\">{{valueLabel()}}</span>\n <!-- Only ever one of these on screen (the active cell), so it keeps the\n tick marks and the rest of its appearance exactly as before. -->\n <mat-slider\n class=\"progress-slider\"\n [min]=\"0\"\n [max]=\"100\"\n [step]=\"1\"\n [discrete]=\"true\"\n [showTickMarks]=\"true\"\n [disabled]=\"!isEditable()\">\n <input\n matSliderThumb\n [ngModel]=\"displayValue()\"\n (ngModelChange)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n [disabled]=\"!isEditable()\">\n </mat-slider>\n</div>\n} @else {\n<!-- Read-only: a plain track + fill rather than a disabled mat-slider.\n The slider mounted here even when the cell was not being edited, and with\n step=1 over 0-100 its tick marks alone were 101 DOM nodes per cell \u2014 on a\n 25-row grid that was 2,525 nodes and the single largest cost in rendering\n the table. It also read as interactive when it was not: the thumb invited\n a drag that did nothing. Double-click still activates, which mounts the\n real slider above. -->\n<div class=\"progress-view-container\" (dblclick)=\"onActivate(); $event.stopPropagation()\">\n <span class=\"progress-value\" [style.color]=\"barColor()\">{{valueLabel()}}</span>\n <div class=\"progress-view-track\">\n <div class=\"progress-view-fill\" [style.width.%]=\"displayValue()\"\n [style.background]=\"barColor()\"></div>\n </div>\n</div>\n}\n", styles: [":root{--mat-slider-with-overlap-handle-outline-color: var(--grid-primary, #6750a4) !important;--mat-slider-with-tick-marks-active-container-color: var(--grid-primary, #6750a4) !important;--mat-slider-handle-height: 12px;--mat-slider-handle-width: 12px;--mat-slider-disabled-active-track-color: var(--grid-primary, #6750a4);--mat-slider-active-track-color: var(--grid-primary, #6750a4)}:host{display:block;height:100%;width:100%}.progress-bar-container{width:100%;height:100%;min-height:30px;position:relative;background:#e0e0e0;border-radius:4px;cursor:pointer}.progress-bar{height:100%;background:var(--grid-primary, #6750a4);transition:width .3s;border-radius:4px}.progress-text{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:var(--grid-font-size-body, 12px);font-weight:500;color:var(--grid-on-surface, #1d1b20);pointer-events:none;z-index:1}.drillable-value{color:inherit;text-decoration:underline;cursor:pointer;pointer-events:auto}.drillable-value:hover{opacity:.8}.progress-input-container{display:flex;flex-direction:row-reverse;align-items:center;padding:4px;width:100%;box-sizing:border-box;overflow:visible;max-height:30px}.progress-input-container.disabled{cursor:pointer}.progress-input-container.disabled .progress-slider{pointer-events:none}.progress-view-container{display:flex;flex-direction:row-reverse;align-items:center;gap:8px;padding:4px;width:100%;box-sizing:border-box;max-height:30px;cursor:pointer}.progress-view-track{flex:1 1 0%;min-width:0;height:4px;border-radius:2px;background:var(--grid-surface-variant, #e0e0e0);overflow:hidden}.progress-view-fill{height:100%;border-radius:2px;background:var(--grid-primary, #6750a4);transition:width .3s}.progress-value{font-size:var(--grid-font-size-body, 12px);font-weight:500;color:var(--grid-on-surface, #1d1b20);flex:0 0 auto;min-width:35px;text-align:right;white-space:nowrap;flex-shrink:0}.progress-slider{flex:1 1 0%;min-width:0!important;max-width:100%!important;overflow:visible}.progress-slider .mdc-slider__track{left:0!important}.progress-slider .mdc-slider{padding-left:0!important;margin-left:0!important}.progress-slider .mdc-slider__value-indicator,.progress-slider .mdc-slider__value-indicator-container{display:none!important;visibility:hidden!important}.progress-slider .mdc-slider__thumb:before,.progress-slider .mdc-slider__thumb:after{display:none!important;content:none!important}.progress-slider .mdc-slider__thumb-knob:before,.progress-slider .mdc-slider__thumb-knob:after{display:none!important;content:none!important}.progress-slider [class*=value-indicator],.progress-slider [class*=tooltip]{display:none!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: MatSliderModule }, { kind: "component", type: i2$4.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "directive", type: i2$4.MatSliderThumb, selector: "input[matSliderThumb]", inputs: ["value"], outputs: ["valueChange", "dragStart", "dragEnd"], exportAs: ["matSliderThumb"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
7456
7498
|
}
|
|
7457
7499
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ProgressComponent, decorators: [{
|
|
7458
7500
|
type: Component,
|
|
@@ -8042,7 +8084,7 @@ class SelectComponent {
|
|
|
8042
8084
|
return undefined;
|
|
8043
8085
|
}
|
|
8044
8086
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8045
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: SelectComponent, isStandalone: true, selector: "eru-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n<mat-form-field [appearance]=\"getProperty('appearance') || 'outline'\" class=\"select-form-field\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"select-container\">\n <mat-select [placeholder]=\"getProperty('placeholder') || ''\" [multiple]=\"multiple()\"\n [disabled]=\"getProperty('disabled') || !isEditable()\" [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\" [compareWith]=\"compareWith\" panelClass=\"select-panel\" class=\"select-input\"\n (selectionChange)=\"onValueChange($event.value)\" (blur)=\"onBlur($event)\" (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n\n <mat-option disabled class=\"search-option\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-form-field [appearance]=\"getProperty('appearance') || 'outline'\" class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input matInput type=\"text\" class=\"search-input\" [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n @if (multiple()) {\n <div class=\"select-all-container\" (click)=\"$event.stopPropagation()\">\n <mat-checkbox [checked]=\"isAllSelected()\" [indeterminate]=\"isIndeterminate()\"\n (change)=\"toggleSelectAll($event.checked)\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"select-all-text\">Select All</span>\n </mat-checkbox>\n </div>\n }\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n @if (multiple()) {\n <mat-option [value]=\"option.value\" (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n {{ option.label }}\n </mat-option>\n } @else {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n }\n </mat-select>\n </div>\n</mat-form-field>\n} @else {\n<div class=\"select-display\" [class.select-display-editable]=\"isEditable()\" (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"select-drillable\" (click)=\"onDrillableClick($event)\">\n {{formatDisplayValue() || (getProperty('placeholder') || '')}}\n </span>\n } @else {\n {{formatDisplayValue() || (getProperty('placeholder') || '')}}\n }\n</div>\n}", styles: ["@charset \"UTF-8\";.select-form-field{width:100%}.select-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.select-container{width:100%}.select-display{width:100%;padding:8px 12px;min-height:30px;display:flex;align-items:center;cursor:default}.select-display.select-display-editable{cursor:pointer}.select-display.select-display-editable:hover{background-color:#0000000a}.select-drillable{color:#1976d2;cursor:pointer;text-decoration:underline}.select-drillable:hover{color:#1565c0}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option mat-pseudo-checkbox{display:none!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important;align-items:stretch!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.search-option .select-all-container{padding:4px 0 4px 12px!important;display:flex!important;align-items:center!important;pointer-events:auto!important}.search-option .select-all-container .select-all-text{font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;font-weight:500!important;color:var(--grid-on-surface, #1d1b20)!important}.search-option .select-all-container mat-checkbox .mdc-checkbox{display:none!important}.search-option .select-all-container mat-checkbox .mdc-form-field{padding:0!important;margin:0!important}.search-option .select-all-container mat-checkbox .mdc-label{padding:0 0 0 12px!important;margin:0!important;cursor:pointer!important}.search-option .select-all-container mat-checkbox.mat-mdc-checkbox-checked .mdc-label:before,.search-option .select-all-container mat-checkbox.mat-mdc-checkbox-indeterminate .mdc-label:before{content:\"\\2713\";font-size:16px;font-weight:700;color:var(--grid-on-surface, #1d1b20);margin-right:4px}.select-panel{min-width:200px!important}.select-input{padding-left:4px}.select-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.select-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.select-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}.select-panel mat-option mat-pseudo-checkbox{display:none!important}.select-panel mat-option.mdc-list-item--selected:not(.search-option) .mdc-list-item__primary-text:before{content:\"\\2713\"!important;font-size:16px;font-weight:700;color:var(--grid-on-surface, #1d1b20);margin-right:8px;display:inline!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
8087
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: SelectComponent, isStandalone: true, selector: "eru-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null }, row: { classPropertyName: "row", publicName: "row", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n<mat-form-field [appearance]=\"getProperty('appearance') || 'outline'\" class=\"select-form-field\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"select-container\">\n <mat-select [placeholder]=\"getProperty('placeholder') || ''\" [multiple]=\"multiple()\"\n [disabled]=\"getProperty('disabled') || !isEditable()\" [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\" [compareWith]=\"compareWith\" panelClass=\"select-panel\" class=\"select-input\"\n (selectionChange)=\"onValueChange($event.value)\" (blur)=\"onBlur($event)\" (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n\n <mat-option disabled class=\"search-option\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-form-field [appearance]=\"getProperty('appearance') || 'outline'\" class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input matInput type=\"text\" class=\"search-input\" [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n @if (multiple()) {\n <div class=\"select-all-container\" (click)=\"$event.stopPropagation()\">\n <mat-checkbox [checked]=\"isAllSelected()\" [indeterminate]=\"isIndeterminate()\"\n (change)=\"toggleSelectAll($event.checked)\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"select-all-text\">Select All</span>\n </mat-checkbox>\n </div>\n }\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n @if (multiple()) {\n <mat-option [value]=\"option.value\" (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n {{ option.label }}\n </mat-option>\n } @else {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n }\n </mat-select>\n </div>\n</mat-form-field>\n} @else {\n<div class=\"select-display\" [class.select-display-editable]=\"isEditable()\" (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"select-drillable\" (click)=\"onDrillableClick($event)\">\n {{formatDisplayValue() || (getProperty('placeholder') || '')}}\n </span>\n } @else {\n {{formatDisplayValue() || (getProperty('placeholder') || '')}}\n }\n</div>\n}", styles: ["@charset \"UTF-8\";.select-form-field{width:100%}.select-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.select-container{width:100%}.select-display{width:100%;padding:8px 12px;min-height:30px;display:flex;align-items:center;cursor:default}.select-display.select-display-editable{cursor:pointer}.select-display.select-display-editable:hover{background-color:#0000000a}.select-drillable{color:#1976d2;cursor:pointer;text-decoration:underline}.select-drillable:hover{color:#1565c0}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option mat-pseudo-checkbox{display:none!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important;align-items:stretch!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.search-option .select-all-container{padding:4px 0 4px 12px!important;display:flex!important;align-items:center!important;pointer-events:auto!important}.search-option .select-all-container .select-all-text{font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;font-weight:500!important;color:var(--grid-on-surface, #1d1b20)!important}.search-option .select-all-container mat-checkbox .mdc-checkbox{display:none!important}.search-option .select-all-container mat-checkbox .mdc-form-field{padding:0!important;margin:0!important}.search-option .select-all-container mat-checkbox .mdc-label{padding:0 0 0 12px!important;margin:0!important;cursor:pointer!important}.search-option .select-all-container mat-checkbox.mat-mdc-checkbox-checked .mdc-label:before,.search-option .select-all-container mat-checkbox.mat-mdc-checkbox-indeterminate .mdc-label:before{content:\"\\2713\";font-size:16px;font-weight:700;color:var(--grid-on-surface, #1d1b20);margin-right:4px}.select-panel{min-width:200px!important}.select-input{padding-left:4px}.select-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.select-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.select-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}.select-panel mat-option mat-pseudo-checkbox{display:none!important}.select-panel mat-option.mdc-list-item--selected:not(.search-option) .mdc-list-item__primary-text:before{content:\"\\2713\"!important;font-size:16px;font-weight:700;color:var(--grid-on-surface, #1d1b20);margin-right:8px;display:inline!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i2$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
8046
8088
|
}
|
|
8047
8089
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: SelectComponent, decorators: [{
|
|
8048
8090
|
type: Component,
|
|
@@ -8244,51 +8286,12 @@ class StatusComponent {
|
|
|
8244
8286
|
}
|
|
8245
8287
|
}
|
|
8246
8288
|
getStatusColor(statusName) {
|
|
8247
|
-
const
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
};
|
|
8254
|
-
}
|
|
8255
|
-
const options = cfg.options || [];
|
|
8256
|
-
// Find option by name (status value matches option.name)
|
|
8257
|
-
const statusOption = options.find((opt) => {
|
|
8258
|
-
return opt.name === statusName;
|
|
8259
|
-
});
|
|
8260
|
-
if (!statusOption || !statusOption.color) {
|
|
8261
|
-
return {
|
|
8262
|
-
background: 'white',
|
|
8263
|
-
border: 'black',
|
|
8264
|
-
text: 'black'
|
|
8265
|
-
};
|
|
8266
|
-
}
|
|
8267
|
-
// Advanced color manipulation function for rounded rectangle display
|
|
8268
|
-
const manipulateColor = (color) => {
|
|
8269
|
-
// Convert hex to RGB
|
|
8270
|
-
const hex = color.replace('#', '');
|
|
8271
|
-
const bigint = parseInt(hex, 16);
|
|
8272
|
-
const r = (bigint >> 16) & 255;
|
|
8273
|
-
const g = (bigint >> 8) & 255;
|
|
8274
|
-
const b = bigint & 255;
|
|
8275
|
-
// Create lighter background
|
|
8276
|
-
const lightenFactor = 0.9; // 90% lighter
|
|
8277
|
-
const bgR = Math.min(255, Math.round(r + (255 - r) * lightenFactor));
|
|
8278
|
-
const bgG = Math.min(255, Math.round(g + (255 - g) * lightenFactor));
|
|
8279
|
-
const bgB = Math.min(255, Math.round(b + (255 - b) * lightenFactor));
|
|
8280
|
-
// Darken text color
|
|
8281
|
-
const darkenFactor = 0.3; // 30% darker
|
|
8282
|
-
const textR = Math.round(r * (1 - darkenFactor));
|
|
8283
|
-
const textG = Math.round(g * (1 - darkenFactor));
|
|
8284
|
-
const textB = Math.round(b * (1 - darkenFactor));
|
|
8285
|
-
return {
|
|
8286
|
-
background: `rgb(${bgR}, ${bgG}, ${bgB})`,
|
|
8287
|
-
border: color,
|
|
8288
|
-
text: `rgb(${textR}, ${textG}, ${textB})`
|
|
8289
|
-
};
|
|
8290
|
-
};
|
|
8291
|
-
return manipulateColor(statusOption.color);
|
|
8289
|
+
const options = this.config()?.options || [];
|
|
8290
|
+
// Status value matches option.name.
|
|
8291
|
+
const statusOption = options.find((opt) => opt.name === statusName);
|
|
8292
|
+
// statusPillColors returns the neutral fallback for a missing colour, so the
|
|
8293
|
+
// no-option and no-colour cases need no separate handling here.
|
|
8294
|
+
return statusPillColors(statusOption?.color);
|
|
8292
8295
|
}
|
|
8293
8296
|
getStatusButtonDisplay(statusName) {
|
|
8294
8297
|
const cfg = this.config();
|
|
@@ -8359,7 +8362,7 @@ class StatusComponent {
|
|
|
8359
8362
|
return `#${toHex(darkerR)}${toHex(darkerG)}${toHex(darkerB)}`;
|
|
8360
8363
|
}
|
|
8361
8364
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: StatusComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8362
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: StatusComponent, isStandalone: true, selector: "eru-status", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n <mat-form-field \n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"status-form-field\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"status-container\">\n <mat-select\n [placeholder]=\"getProperty('placeholder') || 'Select status...'\"\n [disabled]=\"getProperty('disabled') || !isEditable()\"\n [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\"\n [compareWith]=\"compareWith\"\n panelClass=\"status-panel\"\n class=\"status-input\"\n (selectionChange)=\"onValueChange($event.value)\"\n (blur)=\"onBlur($event)\"\n (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n \n <mat-option disabled class=\"search-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"search-input\"\n placeholder=\"filter options...\"\n [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n </mat-option>\n\n <mat-option [value]=\"null\">\n None\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"status-option-content\">\n @if(option.color) {\n <span class=\"status-option-indicator\"\n [style.background-color]=\"option.color\"\n [style.border-color]=\"getDarkerColor(option.color)\"></span>\n }\n <span class=\"status-option-label\">{{ option.label }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </div>\n </mat-form-field>\n} @else {\n @if(currentValue()) {\n <div \n class=\"status-display\"\n [style.background-color]=\"statusColors().background\"\n [style.border-color]=\"statusColors().border\"\n [style.color]=\"statusColors().text\"\n (dblclick)=\"onActivate()\">\n <div class=\"status-display-content\">\n @if (isDrillable()) {\n <span class=\"status-text drillable-value\" (click)=\"onDrillableClick($event)\">\n {{statusDisplay().text}}\n </span>\n } @else {\n <span class=\"status-text\">\n {{statusDisplay().text}}\n </span>\n }\n </div>\n </div>\n } @else {\n <div class=\"status-empty\" (dblclick)=\"onActivate()\"></div>\n }\n}\n\n", styles: [".status-form-field{width:100%}.status-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.status-input{padding-left:4px}.status-container{width:100%}.status-empty{width:100%;min-height:30px;cursor:pointer}.status-display{cursor:pointer;width:auto;min-height:auto;border-radius:var(--grid-pill-radius, 4px);border:1px solid;transition:all .2s ease;display:flex;align-items:center;justify-content:center;padding:var(--grid-pill-padding-y, 2px) var(--grid-pill-padding-x, 10px);font-size:var(--grid-pill-font-size, inherit);font-weight:var(--grid-pill-font-weight, 500);box-sizing:border-box;cursor:default;margin:4px 6px}.status-display:hover{opacity:.9}.status-display-content{cursor:pointer;display:flex;align-items:center;justify-content:center;gap:6px;width:100%}.status-text{text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.status-color-indicator{width:12px;height:12px;border-radius:50%;display:inline-block;flex-shrink:0}.drillable-value{color:inherit;text-decoration:underline;cursor:pointer}.drillable-value:hover{opacity:.8}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important;display:flex!important;flex-direction:column!important;gap:8px!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.status-panel{min-width:150px!important}.status-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.status-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.status-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}.mat-select-panel-animations-enabled mat-option:last-of-type mat-pseudo-checkbox,.mat-select-panel-animations-enabled mat-option:first-of-type mat-pseudo-checkbox{display:none!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important;display:flex!important;align-items:center!important}mat-option .status-option-content{display:flex;align-items:center;gap:8px;width:100%}mat-option .status-option-indicator{width:12px;height:12px;border-radius:50%;display:inline-block;flex-shrink:0;border:1.5px solid}mat-option .status-option-label{flex:1;color:var(--grid-on-surface, #1d1b20);font-size:var(--grid-font-size-body, 12px);font-weight:400}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatButtonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
8365
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: StatusComponent, isStandalone: true, selector: "eru-status", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n <mat-form-field \n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"status-form-field\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"status-container\">\n <mat-select\n [placeholder]=\"getProperty('placeholder') || 'Select status...'\"\n [disabled]=\"getProperty('disabled') || !isEditable()\"\n [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\"\n [compareWith]=\"compareWith\"\n panelClass=\"status-panel\"\n class=\"status-input\"\n (selectionChange)=\"onValueChange($event.value)\"\n (blur)=\"onBlur($event)\"\n (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n \n <mat-option disabled class=\"search-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"search-input\"\n placeholder=\"filter options...\"\n [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n </mat-option>\n\n <mat-option [value]=\"null\">\n None\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"status-option-content\">\n @if(option.color) {\n <span class=\"status-option-indicator\"\n [style.background-color]=\"option.color\"\n [style.border-color]=\"getDarkerColor(option.color)\"></span>\n }\n <span class=\"status-option-label\">{{ option.label }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </div>\n </mat-form-field>\n} @else {\n @if(currentValue()) {\n <div \n class=\"status-display\"\n [style.background-color]=\"statusColors().background\"\n [style.border-color]=\"statusColors().border\"\n [style.color]=\"statusColors().text\"\n (dblclick)=\"onActivate()\">\n <div class=\"status-display-content\">\n @if (isDrillable()) {\n <span class=\"status-text drillable-value\" (click)=\"onDrillableClick($event)\">\n {{statusDisplay().text}}\n </span>\n } @else {\n <span class=\"status-text\">\n {{statusDisplay().text}}\n </span>\n }\n </div>\n </div>\n } @else {\n <div class=\"status-empty\" (dblclick)=\"onActivate()\"></div>\n }\n}\n\n", styles: [".status-form-field{width:100%}.status-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.status-input{padding-left:4px}.status-container{width:100%}.status-empty{width:100%;min-height:30px;cursor:pointer}.status-display{cursor:pointer;width:auto;min-height:auto;border-radius:var(--grid-pill-radius, 4px);border:1px solid;transition:all .2s ease;display:flex;align-items:center;justify-content:center;padding:var(--grid-pill-padding-y, 2px) var(--grid-pill-padding-x, 10px);font-size:var(--grid-pill-font-size, inherit);font-weight:var(--grid-pill-font-weight, 500);box-sizing:border-box;cursor:default;margin:4px 6px}.status-display:hover{opacity:.9}.status-display-content{cursor:pointer;display:flex;align-items:center;justify-content:center;gap:6px;width:100%}.status-text{text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.status-color-indicator{width:12px;height:12px;border-radius:50%;display:inline-block;flex-shrink:0}.drillable-value{color:inherit;text-decoration:underline;cursor:pointer}.drillable-value:hover{opacity:.8}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important;display:flex!important;flex-direction:column!important;gap:8px!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.status-panel{min-width:150px!important}.status-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.status-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.status-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}.mat-select-panel-animations-enabled mat-option:last-of-type mat-pseudo-checkbox,.mat-select-panel-animations-enabled mat-option:first-of-type mat-pseudo-checkbox{display:none!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important;display:flex!important;align-items:center!important}mat-option .status-option-content{display:flex;align-items:center;gap:8px;width:100%}mat-option .status-option-indicator{width:12px;height:12px;border-radius:50%;display:inline-block;flex-shrink:0;border:1.5px solid}mat-option .status-option-label{flex:1;color:var(--grid-on-surface, #1d1b20);font-size:var(--grid-font-size-body, 12px);font-weight:400}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatButtonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
8363
8366
|
}
|
|
8364
8367
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: StatusComponent, decorators: [{
|
|
8365
8368
|
type: Component,
|
|
@@ -8411,6 +8414,8 @@ class TagComponent {
|
|
|
8411
8414
|
newTagInput = signal('', ...(ngDevMode ? [{ debugName: "newTagInput" }] : []));
|
|
8412
8415
|
newTagColor = signal('#cccccc', ...(ngDevMode ? [{ debugName: "newTagColor" }] : []));
|
|
8413
8416
|
newlyAddedTags = signal([], ...(ngDevMode ? [{ debugName: "newlyAddedTags" }] : []));
|
|
8417
|
+
/** Show the filter box inside the dropdown. Configurable, as in select and people. */
|
|
8418
|
+
isSearchable = computed(() => this.config()?.searchable !== false, ...(ngDevMode ? [{ debugName: "isSearchable" }] : []));
|
|
8414
8419
|
// Computed properties for Select All functionality
|
|
8415
8420
|
isAllSelected = computed(() => {
|
|
8416
8421
|
const value = this.currentValue();
|
|
@@ -8725,7 +8730,7 @@ class TagComponent {
|
|
|
8725
8730
|
this.newTagColor.set('#cccccc');
|
|
8726
8731
|
}
|
|
8727
8732
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: TagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8728
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: TagComponent, isStandalone: true, selector: "eru-tag", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange", newTagAdded: "newTagAdded" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n <mat-form-field \n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"tag-form-field\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"tag-container\">\n <mat-select\n [placeholder]=\"getProperty('placeholder') || ''\"\n [multiple]=\"true\"\n [disabled]=\"getProperty('disabled') || !isEditable()\"\n [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\"\n [compareWith]=\"compareWith\"\n panelClass=\"tag-panel\"\n (selectionChange)=\"onValueChange($event.value)\"\n (blur)=\"onBlur($event)\"\n (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n \n <mat-option disabled class=\"search-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"search-input\"\n placeholder=\"filter options...\"\n [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n <div class=\"select-all-container\" (click)=\"$event.stopPropagation()\">\n <mat-checkbox \n [checked]=\"isAllSelected()\" \n [indeterminate]=\"isIndeterminate()\"\n (change)=\"toggleSelectAll($event.checked)\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"select-all-text\">Select All</span>\n </mat-checkbox>\n </div>\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\" \n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\" \n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"tag-option\" \n [style.background]=\"getTagColor(option.value).background\" \n [style.color]=\"getTagColor(option.value).color\">\n {{ option.label }}\n </span>\n </mat-option>\n }\n\n <mat-option class=\"add-tag-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"add-tag-container\" (click)=\"$event.stopPropagation()\">\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"add-tag-form-field\">\n <mat-label>Add new tag</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"add-tag-input\"\n placeholder=\"Enter tag name...\"\n [value]=\"newTagInput()\"\n (input)=\"onNewTagInputChange($any($event.target).value)\"\n (keydown.enter)=\"addNewTag()\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n <div class=\"add-tag-actions\">\n <input\n type=\"color\"\n class=\"add-tag-color-picker\"\n [value]=\"newTagColor()\"\n (input)=\"onNewTagColorChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n title=\"Select tag color\">\n <button\n mat-icon-button\n class=\"add-tag-button\"\n [disabled]=\"!canAddNewTag()\"\n (click)=\"addNewTag(); $event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </div>\n </mat-option>\n\n </mat-select>\n </div>\n </mat-form-field>\n} @else {\n <div \n class=\"tag-display\" \n [class.tag-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n @for (tag of tagDisplay().displayTags; track tag) {\n <span class=\"tag\" \n [style.background]=\"getTagColor(tag).background\" \n [style.color]=\"getTagColor(tag).color\">\n {{tag}}\n </span>\n }\n @if(tagDisplay().moreCount > 0) {\n <span class=\"tag\">\n + {{tagDisplay().moreCount}}\n </span>\n }\n </span>\n } @else {\n @for (tag of tagDisplay().displayTags; track tag) {\n <span class=\"tag\" \n [style.background]=\"getTagColor(tag).background\" \n [style.color]=\"getTagColor(tag).color\">\n {{tag}}\n </span>\n }\n @if(tagDisplay().moreCount > 0) {\n <span class=\"tag-more\">\n + {{tagDisplay().moreCount}}\n </span>\n }\n }\n </div>\n}\n\n", styles: [".tag-form-field{width:100%}.tag-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.tag-container{width:100%}.tag-display{width:100%;padding:8px 12px;min-height:30px;display:flex;flex-wrap:wrap;align-items:center;gap:4px;cursor:default}.tag-display.tag-display-editable{cursor:pointer}.tag-display.tag-display-editable:hover{background-color:#0000000a}.tag{display:inline-block;padding:var(--grid-pill-padding-y, 3px) var(--grid-pill-padding-x, 10px);border-radius:var(--grid-pill-radius, 12px);font-size:var(--grid-pill-font-size, var(--grid-font-size-body, 12px));font-weight:var(--grid-pill-font-weight, 500);white-space:nowrap;line-height:1.2}.tag-more{display:inline-block;border-radius:var(--grid-pill-radius, 12px);background-color:var(--grid-surface-container-high, #f5f5f5);color:var(--grid-on-surface-variant, #49454f);font-size:var(--grid-pill-font-size, var(--grid-font-size-body, 12px));font-weight:var(--grid-pill-font-weight, 700);font-style:italic;padding:var(--grid-pill-padding-y, 3px) var(--grid-pill-padding-x, 10px);white-space:nowrap;line-height:1.2}.drillable-value{display:flex;flex-wrap:wrap;gap:4px;align-items:center;cursor:pointer}.drillable-value .tag{text-decoration:underline}.add-option{position:sticky;position:-webkit-sticky;bottom:0;z-index:3;background:var(--grid-surface-container-high, #fff);box-shadow:0 -2px 8px -4px #00000017;border-top:1px solid var(--grid-outline-variant, #e0e0e0)}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important;display:flex!important;flex-direction:column!important;gap:8px!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.search-option .select-all-container{padding:4px 0!important;display:flex!important;align-items:center!important;pointer-events:auto!important}.search-option .select-all-container .select-all-text{font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;font-weight:500!important;color:var(--grid-on-surface, #1d1b20)!important}.search-option .select-all-container mat-checkbox .mdc-checkbox .mdc-checkbox__checkmark{color:var(--grid-on-primary, #ffffff)!important}.search-option .select-all-container mat-checkbox.mat-mdc-checkbox-checked .mdc-checkbox__background{background-color:var(--grid-primary, #6750a4)!important;border-color:var(--grid-primary, #6750a4)!important}.search-option .select-all-container mat-checkbox.mat-mdc-checkbox-indeterminate .mdc-checkbox__background{background-color:var(--grid-primary, #6750a4)!important;border-color:var(--grid-primary, #6750a4)!important}.tag-panel-footer{position:absolute;bottom:0;left:0;right:0;background:#fff;border-top:1px solid rgba(0,0,0,.12);padding:8px;z-index:10;box-shadow:0 -2px 4px #0000001a}.tag-panel-footer .add-tag-container{display:flex;align-items:center;gap:8px;width:100%;pointer-events:auto}.tag-panel-footer .add-tag-form-field-wrapper{flex:1;min-width:0;position:relative}.tag-panel-footer .new-tag-input{width:100%;border:1px solid rgba(0,0,0,.38);border-radius:4px;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 12px;font-family:var(--grid-font-family, \"Poppins\")!important;box-sizing:border-box;cursor:text}.tag-panel-footer .new-tag-input:focus{border-color:var(--grid-primary, #6750a4);border-width:2px}.tag-panel-footer .add-tag-button{flex-shrink:0;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 16px!important;min-width:auto!important;pointer-events:auto!important;background-color:var(--grid-primary, #6750a4);color:#fff;border:none;border-radius:4px;cursor:pointer;font-family:var(--grid-font-family, \"Poppins\")!important}.tag-panel-footer .add-tag-button:hover:not([disabled]){opacity:.9}.tag-panel-footer .add-tag-button[disabled]{opacity:.5;cursor:not-allowed}.cdk-overlay-pane.tag-panel-overlay{position:relative;padding-bottom:60px!important}.cdk-overlay-pane.tag-panel-overlay .mat-mdc-select-panel{max-height:calc(100% - 60px)!important}.add-tag-option{position:sticky!important;background:var(--grid-surface-container, #fff)!important;bottom:-10px!important;z-index:10!important;padding:8px 8px 10px!important;margin-top:auto!important;margin-bottom:0!important;box-shadow:0 -2px 8px #00000026!important;border-top:1px solid rgba(0,0,0,.12)!important}.add-tag-option:hover{background:var(--grid-surface-container, #fff)!important}.add-tag-option .mat-mdc-option{min-height:auto!important;padding:0!important;height:auto!important}.add-tag-option .mat-mdc-option:hover{background:var(--grid-surface-container, #fff)!important}.add-tag-option .mdc-list-item__primary-text{width:100%!important;padding:0!important;margin:0!important}.add-tag-option .add-tag-container{display:flex;align-items:center;gap:8px;width:100%;padding:0;margin-bottom:0}.add-tag-option .add-tag-form-field{flex:1;min-width:0}.add-tag-option .add-tag-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.add-tag-option .add-tag-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-infix{min-height:auto!important;padding:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.add-tag-option .add-tag-actions{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;flex-shrink:0}.add-tag-option .add-tag-color-picker{flex-shrink:0;width:20px;height:20px;border:1px solid rgba(0,0,0,.12);border-radius:4px;cursor:pointer;padding:2px;background:transparent;box-sizing:border-box;margin:0 auto}.add-tag-option .add-tag-color-picker::-webkit-color-swatch-wrapper{padding:0}.add-tag-option .add-tag-color-picker::-webkit-color-swatch{border:none;border-radius:2px}.add-tag-option .add-tag-color-picker::-moz-color-swatch{border:none;border-radius:2px}.add-tag-option .add-tag-color-picker:hover{border-color:var(--grid-primary, #6750a4)}.add-tag-option .add-tag-color-picker:focus{outline:2px solid var(--grid-primary, #6750a4);outline-offset:2px}.add-tag-option .add-tag-button{flex-shrink:0;width:20px;height:20px;color:var(--grid-primary, #6750a4)!important;display:flex!important;align-items:center!important;justify-content:center!important;margin:0 auto}.add-tag-option .add-tag-button:not([disabled]){color:var(--grid-primary, #6750a4)!important}.add-tag-option .add-tag-button:not([disabled]):hover{background-color:#6750a414!important}.add-tag-option .add-tag-button[disabled]{opacity:.38;color:#00000061!important}.add-tag-option .add-tag-button mat-icon{font-size:24px;width:24px;height:24px;line-height:24px;display:flex;align-items:center;justify-content:center;margin-right:0}.tag-panel mat-option:last-of-type mat-pseudo-checkbox,.tag-panel mat-option:first-of-type mat-pseudo-checkbox{display:none!important}.tag-panel{min-width:200px!important}.tag-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.tag-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.tag-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important;display:flex!important;align-items:center!important}mat-option .tag-option{display:inline-block;padding:4px 8px;border-radius:12px;font-size:var(--grid-font-size-body, 12px);font-weight:500;white-space:nowrap;line-height:1.2}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
8733
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: TagComponent, isStandalone: true, selector: "eru-tag", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange", newTagAdded: "newTagAdded" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n <mat-form-field \n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"tag-form-field\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"tag-container\">\n <mat-select\n [placeholder]=\"getProperty('placeholder') || ''\"\n [multiple]=\"true\"\n [disabled]=\"getProperty('disabled') || !isEditable()\"\n [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\"\n [compareWith]=\"compareWith\"\n panelClass=\"tag-panel\"\n (selectionChange)=\"onValueChange($event.value)\"\n (blur)=\"onBlur($event)\"\n (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n \n <mat-option disabled class=\"search-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n @if (isSearchable()) {\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"search-input\"\n [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n }\n <div class=\"select-all-container mat-mdc-option mdc-list-item\"\n [class.mdc-list-item--selected]=\"isAllSelected() || isIndeterminate()\"\n [class.select-all-partial]=\"isIndeterminate()\"\n (click)=\"toggleSelectAll(!isAllSelected()); $event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-pseudo-checkbox\n class=\"mat-mdc-option-pseudo-checkbox select-all-checkbox\"\n [state]=\"isIndeterminate() ? 'indeterminate' : (isAllSelected() ? 'checked' : 'unchecked')\"></mat-pseudo-checkbox>\n <span class=\"mdc-list-item__primary-text select-all-text\">Select All</span>\n </div>\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\" \n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\" \n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"tag-option\" \n [style.background]=\"getTagColor(option.value).background\" \n [style.color]=\"getTagColor(option.value).color\">\n {{ option.label }}\n </span>\n </mat-option>\n }\n\n <mat-option class=\"add-tag-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"add-tag-container\" (click)=\"$event.stopPropagation()\">\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"add-tag-form-field\">\n <mat-label>Add new tag</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"add-tag-input\"\n [value]=\"newTagInput()\"\n (input)=\"onNewTagInputChange($any($event.target).value)\"\n (keydown.enter)=\"addNewTag()\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n <div class=\"add-tag-actions\">\n <input\n type=\"color\"\n class=\"add-tag-color-picker\"\n [value]=\"newTagColor()\"\n (input)=\"onNewTagColorChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n title=\"Select tag color\">\n <button\n mat-icon-button\n class=\"add-tag-button\"\n [disabled]=\"!canAddNewTag()\"\n (click)=\"addNewTag(); $event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </div>\n </mat-option>\n\n </mat-select>\n </div>\n </mat-form-field>\n} @else {\n <div \n class=\"tag-display\" \n [class.tag-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n @for (tag of tagDisplay().displayTags; track tag) {\n <span class=\"tag\" \n [style.background]=\"getTagColor(tag).background\" \n [style.color]=\"getTagColor(tag).color\">\n {{tag}}\n </span>\n }\n @if(tagDisplay().moreCount > 0) {\n <span class=\"tag\">\n + {{tagDisplay().moreCount}}\n </span>\n }\n </span>\n } @else {\n @for (tag of tagDisplay().displayTags; track tag) {\n <span class=\"tag\" \n [style.background]=\"getTagColor(tag).background\" \n [style.color]=\"getTagColor(tag).color\">\n {{tag}}\n </span>\n }\n @if(tagDisplay().moreCount > 0) {\n <span class=\"tag-more\">\n + {{tagDisplay().moreCount}}\n </span>\n }\n }\n </div>\n}\n\n", styles: [".tag-form-field{width:100%}.tag-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.tag-container{width:100%}.tag-display{width:100%;padding:8px 12px;min-height:30px;display:flex;flex-wrap:wrap;align-items:center;gap:4px;cursor:default}.tag-display.tag-display-editable{cursor:pointer}.tag-display.tag-display-editable:hover{background-color:#0000000a}.tag{display:inline-block;padding:var(--grid-pill-padding-y, 3px) var(--grid-pill-padding-x, 10px);border-radius:var(--grid-pill-radius, 12px);font-size:var(--grid-pill-font-size, var(--grid-font-size-body, 12px));font-weight:var(--grid-pill-font-weight, 500);white-space:nowrap;line-height:1.2}.tag-more{display:inline-block;border-radius:var(--grid-pill-radius, 12px);background-color:var(--grid-surface-container-high, #f5f5f5);color:var(--grid-on-surface-variant, #49454f);font-size:var(--grid-pill-font-size, var(--grid-font-size-body, 12px));font-weight:var(--grid-pill-font-weight, 700);font-style:italic;padding:var(--grid-pill-padding-y, 3px) var(--grid-pill-padding-x, 10px);white-space:nowrap;line-height:1.2}.drillable-value{display:flex;flex-wrap:wrap;gap:4px;align-items:center;cursor:pointer}.drillable-value .tag{text-decoration:underline}.add-option{position:sticky;position:-webkit-sticky;bottom:0;z-index:3;background:var(--grid-surface-container-high, #fff);box-shadow:0 -2px 8px -4px #00000017;border-top:1px solid var(--grid-outline-variant, #e0e0e0)}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important;display:flex!important;flex-direction:column!important;gap:8px!important;opacity:1!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.search-option .select-all-container{padding:4px 0!important;min-height:auto!important;display:flex!important;align-items:center!important;pointer-events:auto!important;cursor:pointer!important;background:transparent!important}.search-option .select-all-container:hover{background:var(--grid-row-hover, rgba(0, 0, 0, .04))!important}.search-option .select-all-container .select-all-text{display:inline-flex!important;flex-direction:row!important;align-items:center!important;width:auto!important;max-width:none!important;gap:0!important;font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;font-weight:500!important;color:var(--grid-on-surface, #1d1b20)!important}.search-option .select-all-container.select-all-partial .select-all-text:before,.search-option .select-all-container.select-all-partial .select-all-checkbox{opacity:.5}.tag-panel-footer{position:absolute;bottom:0;left:0;right:0;background:#fff;border-top:1px solid rgba(0,0,0,.12);padding:8px;z-index:10;box-shadow:0 -2px 4px #0000001a}.tag-panel-footer .add-tag-container{display:flex;align-items:center;gap:8px;width:100%;pointer-events:auto}.tag-panel-footer .add-tag-form-field-wrapper{flex:1;min-width:0;position:relative}.tag-panel-footer .new-tag-input{width:100%;border:1px solid rgba(0,0,0,.38);border-radius:4px;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 12px;font-family:var(--grid-font-family, \"Poppins\")!important;box-sizing:border-box;cursor:text}.tag-panel-footer .new-tag-input:focus{border-color:var(--grid-primary, #6750a4);border-width:2px}.tag-panel-footer .add-tag-button{flex-shrink:0;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 16px!important;min-width:auto!important;pointer-events:auto!important;background-color:var(--grid-primary, #6750a4);color:#fff;border:none;border-radius:4px;cursor:pointer;font-family:var(--grid-font-family, \"Poppins\")!important}.tag-panel-footer .add-tag-button:hover:not([disabled]){opacity:.9}.tag-panel-footer .add-tag-button[disabled]{opacity:.5;cursor:not-allowed}.cdk-overlay-pane.tag-panel-overlay{position:relative;padding-bottom:60px!important}.cdk-overlay-pane.tag-panel-overlay .mat-mdc-select-panel{max-height:calc(100% - 60px)!important}.add-tag-option{position:sticky!important;background:var(--grid-surface, #fff)!important;bottom:-10px!important;z-index:10!important;padding:8px 8px 10px!important;margin-top:auto!important;margin-bottom:0!important;box-shadow:0 -2px 8px #00000026!important;border-top:1px solid rgba(0,0,0,.12)!important}.add-tag-option:hover{background:var(--grid-surface, #fff)!important}.add-tag-option .mat-mdc-option{min-height:auto!important;padding:0!important;height:auto!important}.add-tag-option .mat-mdc-option:hover{background:var(--grid-surface, #fff)!important}.add-tag-option .mdc-list-item__primary-text{width:100%!important;padding:0!important;margin:0!important}.add-tag-option .add-tag-container{display:flex;align-items:center;gap:8px;width:100%;padding:0;margin-bottom:0}.add-tag-option .add-tag-form-field{flex:1;min-width:0}.add-tag-option .add-tag-form-field .mat-mdc-form-field-focus-overlay{background:transparent!important}.add-tag-option .add-tag-form-field .mdc-notched-outline__leading,.add-tag-option .add-tag-form-field .mdc-notched-outline__notch,.add-tag-option .add-tag-form-field .mdc-notched-outline__trailing{border-color:var(--grid-outline-variant, #cac4d0)!important;border-width:1px!important}.add-tag-option .add-tag-form-field.mat-focused .mdc-notched-outline__leading,.add-tag-option .add-tag-form-field.mat-focused .mdc-notched-outline__notch,.add-tag-option .add-tag-form-field.mat-focused .mdc-notched-outline__trailing{border-color:var(--grid-outline, #79747e)!important}.add-tag-option .add-tag-form-field .mdc-floating-label,.add-tag-option .add-tag-form-field label{color:var(--grid-on-surface-variant, #49454f)!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.add-tag-option .add-tag-form-field .mat-mdc-text-field-wrapper{background:transparent!important;padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-infix{min-height:auto!important;padding:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.add-tag-option .add-tag-actions{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;flex-shrink:0}.add-tag-option .add-tag-color-picker{flex-shrink:0;width:20px;height:20px;border:1px solid rgba(0,0,0,.12);border-radius:4px;cursor:pointer;padding:2px;background:transparent;box-sizing:border-box;margin:0 auto}.add-tag-option .add-tag-color-picker::-webkit-color-swatch-wrapper{padding:0}.add-tag-option .add-tag-color-picker::-webkit-color-swatch{border:none;border-radius:2px}.add-tag-option .add-tag-color-picker::-moz-color-swatch{border:none;border-radius:2px}.add-tag-option .add-tag-color-picker:hover{border-color:var(--grid-primary, #6750a4)}.add-tag-option .add-tag-color-picker:focus{outline:2px solid var(--grid-primary, #6750a4);outline-offset:2px}.add-tag-option .add-tag-button{flex-shrink:0;width:20px;height:20px;color:var(--grid-primary, #6750a4)!important;display:flex!important;align-items:center!important;justify-content:center!important;margin:0 auto}.add-tag-option .add-tag-button:not([disabled]){color:var(--grid-primary, #6750a4)!important}.add-tag-option .add-tag-button:not([disabled]):hover{background-color:#6750a414!important}.add-tag-option .add-tag-button[disabled]{opacity:.38;color:#00000061!important}.add-tag-option .add-tag-button mat-icon{font-size:24px;width:24px;height:24px;line-height:24px;display:flex;align-items:center;justify-content:center;margin-right:0}.tag-panel .search-option>mat-pseudo-checkbox,.tag-panel .search-option>.mat-mdc-option-pseudo-checkbox,.tag-panel .add-tag-option>mat-pseudo-checkbox,.tag-panel .add-tag-option>.mat-mdc-option-pseudo-checkbox{display:none!important}.tag-panel{min-width:200px!important}.tag-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.tag-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.tag-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important;display:flex!important;align-items:center!important}mat-option .tag-option{display:inline-block;padding:4px 8px;border-radius:12px;font-size:var(--grid-font-size-body, 12px);font-weight:500;white-space:nowrap;line-height:1.2}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatPseudoCheckboxModule }, { kind: "component", type: i1$1.MatPseudoCheckbox, selector: "mat-pseudo-checkbox", inputs: ["state", "disabled", "appearance"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
8729
8734
|
}
|
|
8730
8735
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: TagComponent, decorators: [{
|
|
8731
8736
|
type: Component,
|
|
@@ -8735,11 +8740,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
8735
8740
|
MatSelectModule,
|
|
8736
8741
|
MatInputModule,
|
|
8737
8742
|
MatOptionModule,
|
|
8743
|
+
MatPseudoCheckboxModule,
|
|
8738
8744
|
MatChipsModule,
|
|
8739
|
-
MatCheckboxModule,
|
|
8740
8745
|
MatButtonModule,
|
|
8741
8746
|
MatIconModule
|
|
8742
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if(isActive()) {\n <mat-form-field \n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"tag-form-field\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"tag-container\">\n <mat-select\n [placeholder]=\"getProperty('placeholder') || ''\"\n [multiple]=\"true\"\n [disabled]=\"getProperty('disabled') || !isEditable()\"\n [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\"\n [compareWith]=\"compareWith\"\n panelClass=\"tag-panel\"\n (selectionChange)=\"onValueChange($event.value)\"\n (blur)=\"onBlur($event)\"\n (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n \n <mat-option disabled class=\"search-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"search-input\"\n placeholder=\"filter options...\"\n [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n <div class=\"select-all-container\" (click)=\"$event.stopPropagation()\">\n <mat-checkbox \n [checked]=\"isAllSelected()\" \n [indeterminate]=\"isIndeterminate()\"\n (change)=\"toggleSelectAll($event.checked)\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"select-all-text\">Select All</span>\n </mat-checkbox>\n </div>\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\" \n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\" \n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"tag-option\" \n [style.background]=\"getTagColor(option.value).background\" \n [style.color]=\"getTagColor(option.value).color\">\n {{ option.label }}\n </span>\n </mat-option>\n }\n\n <mat-option class=\"add-tag-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"add-tag-container\" (click)=\"$event.stopPropagation()\">\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"add-tag-form-field\">\n <mat-label>Add new tag</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"add-tag-input\"\n placeholder=\"Enter tag name...\"\n [value]=\"newTagInput()\"\n (input)=\"onNewTagInputChange($any($event.target).value)\"\n (keydown.enter)=\"addNewTag()\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n <div class=\"add-tag-actions\">\n <input\n type=\"color\"\n class=\"add-tag-color-picker\"\n [value]=\"newTagColor()\"\n (input)=\"onNewTagColorChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n title=\"Select tag color\">\n <button\n mat-icon-button\n class=\"add-tag-button\"\n [disabled]=\"!canAddNewTag()\"\n (click)=\"addNewTag(); $event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </div>\n </mat-option>\n\n </mat-select>\n </div>\n </mat-form-field>\n} @else {\n <div \n class=\"tag-display\" \n [class.tag-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n @for (tag of tagDisplay().displayTags; track tag) {\n <span class=\"tag\" \n [style.background]=\"getTagColor(tag).background\" \n [style.color]=\"getTagColor(tag).color\">\n {{tag}}\n </span>\n }\n @if(tagDisplay().moreCount > 0) {\n <span class=\"tag\">\n + {{tagDisplay().moreCount}}\n </span>\n }\n </span>\n } @else {\n @for (tag of tagDisplay().displayTags; track tag) {\n <span class=\"tag\" \n [style.background]=\"getTagColor(tag).background\" \n [style.color]=\"getTagColor(tag).color\">\n {{tag}}\n </span>\n }\n @if(tagDisplay().moreCount > 0) {\n <span class=\"tag-more\">\n + {{tagDisplay().moreCount}}\n </span>\n }\n }\n </div>\n}\n\n", styles: [".tag-form-field{width:100%}.tag-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.tag-container{width:100%}.tag-display{width:100%;padding:8px 12px;min-height:30px;display:flex;flex-wrap:wrap;align-items:center;gap:4px;cursor:default}.tag-display.tag-display-editable{cursor:pointer}.tag-display.tag-display-editable:hover{background-color:#0000000a}.tag{display:inline-block;padding:var(--grid-pill-padding-y, 3px) var(--grid-pill-padding-x, 10px);border-radius:var(--grid-pill-radius, 12px);font-size:var(--grid-pill-font-size, var(--grid-font-size-body, 12px));font-weight:var(--grid-pill-font-weight, 500);white-space:nowrap;line-height:1.2}.tag-more{display:inline-block;border-radius:var(--grid-pill-radius, 12px);background-color:var(--grid-surface-container-high, #f5f5f5);color:var(--grid-on-surface-variant, #49454f);font-size:var(--grid-pill-font-size, var(--grid-font-size-body, 12px));font-weight:var(--grid-pill-font-weight, 700);font-style:italic;padding:var(--grid-pill-padding-y, 3px) var(--grid-pill-padding-x, 10px);white-space:nowrap;line-height:1.2}.drillable-value{display:flex;flex-wrap:wrap;gap:4px;align-items:center;cursor:pointer}.drillable-value .tag{text-decoration:underline}.add-option{position:sticky;position:-webkit-sticky;bottom:0;z-index:3;background:var(--grid-surface-container-high, #fff);box-shadow:0 -2px 8px -4px #00000017;border-top:1px solid var(--grid-outline-variant, #e0e0e0)}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important;display:flex!important;flex-direction:column!important;gap:8px!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.search-option .select-all-container{padding:4px 0!important;display:flex!important;align-items:center!important;pointer-events:auto!important}.search-option .select-all-container .select-all-text{font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;font-weight:500!important;color:var(--grid-on-surface, #1d1b20)!important}.search-option .select-all-container mat-checkbox .mdc-checkbox .mdc-checkbox__checkmark{color:var(--grid-on-primary, #ffffff)!important}.search-option .select-all-container mat-checkbox.mat-mdc-checkbox-checked .mdc-checkbox__background{background-color:var(--grid-primary, #6750a4)!important;border-color:var(--grid-primary, #6750a4)!important}.search-option .select-all-container mat-checkbox.mat-mdc-checkbox-indeterminate .mdc-checkbox__background{background-color:var(--grid-primary, #6750a4)!important;border-color:var(--grid-primary, #6750a4)!important}.tag-panel-footer{position:absolute;bottom:0;left:0;right:0;background:#fff;border-top:1px solid rgba(0,0,0,.12);padding:8px;z-index:10;box-shadow:0 -2px 4px #0000001a}.tag-panel-footer .add-tag-container{display:flex;align-items:center;gap:8px;width:100%;pointer-events:auto}.tag-panel-footer .add-tag-form-field-wrapper{flex:1;min-width:0;position:relative}.tag-panel-footer .new-tag-input{width:100%;border:1px solid rgba(0,0,0,.38);border-radius:4px;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 12px;font-family:var(--grid-font-family, \"Poppins\")!important;box-sizing:border-box;cursor:text}.tag-panel-footer .new-tag-input:focus{border-color:var(--grid-primary, #6750a4);border-width:2px}.tag-panel-footer .add-tag-button{flex-shrink:0;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 16px!important;min-width:auto!important;pointer-events:auto!important;background-color:var(--grid-primary, #6750a4);color:#fff;border:none;border-radius:4px;cursor:pointer;font-family:var(--grid-font-family, \"Poppins\")!important}.tag-panel-footer .add-tag-button:hover:not([disabled]){opacity:.9}.tag-panel-footer .add-tag-button[disabled]{opacity:.5;cursor:not-allowed}.cdk-overlay-pane.tag-panel-overlay{position:relative;padding-bottom:60px!important}.cdk-overlay-pane.tag-panel-overlay .mat-mdc-select-panel{max-height:calc(100% - 60px)!important}.add-tag-option{position:sticky!important;background:var(--grid-surface-container, #fff)!important;bottom:-10px!important;z-index:10!important;padding:8px 8px 10px!important;margin-top:auto!important;margin-bottom:0!important;box-shadow:0 -2px 8px #00000026!important;border-top:1px solid rgba(0,0,0,.12)!important}.add-tag-option:hover{background:var(--grid-surface-container, #fff)!important}.add-tag-option .mat-mdc-option{min-height:auto!important;padding:0!important;height:auto!important}.add-tag-option .mat-mdc-option:hover{background:var(--grid-surface-container, #fff)!important}.add-tag-option .mdc-list-item__primary-text{width:100%!important;padding:0!important;margin:0!important}.add-tag-option .add-tag-container{display:flex;align-items:center;gap:8px;width:100%;padding:0;margin-bottom:0}.add-tag-option .add-tag-form-field{flex:1;min-width:0}.add-tag-option .add-tag-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.add-tag-option .add-tag-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-infix{min-height:auto!important;padding:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.add-tag-option .add-tag-actions{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;flex-shrink:0}.add-tag-option .add-tag-color-picker{flex-shrink:0;width:20px;height:20px;border:1px solid rgba(0,0,0,.12);border-radius:4px;cursor:pointer;padding:2px;background:transparent;box-sizing:border-box;margin:0 auto}.add-tag-option .add-tag-color-picker::-webkit-color-swatch-wrapper{padding:0}.add-tag-option .add-tag-color-picker::-webkit-color-swatch{border:none;border-radius:2px}.add-tag-option .add-tag-color-picker::-moz-color-swatch{border:none;border-radius:2px}.add-tag-option .add-tag-color-picker:hover{border-color:var(--grid-primary, #6750a4)}.add-tag-option .add-tag-color-picker:focus{outline:2px solid var(--grid-primary, #6750a4);outline-offset:2px}.add-tag-option .add-tag-button{flex-shrink:0;width:20px;height:20px;color:var(--grid-primary, #6750a4)!important;display:flex!important;align-items:center!important;justify-content:center!important;margin:0 auto}.add-tag-option .add-tag-button:not([disabled]){color:var(--grid-primary, #6750a4)!important}.add-tag-option .add-tag-button:not([disabled]):hover{background-color:#6750a414!important}.add-tag-option .add-tag-button[disabled]{opacity:.38;color:#00000061!important}.add-tag-option .add-tag-button mat-icon{font-size:24px;width:24px;height:24px;line-height:24px;display:flex;align-items:center;justify-content:center;margin-right:0}.tag-panel mat-option:last-of-type mat-pseudo-checkbox,.tag-panel mat-option:first-of-type mat-pseudo-checkbox{display:none!important}.tag-panel{min-width:200px!important}.tag-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.tag-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.tag-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important;display:flex!important;align-items:center!important}mat-option .tag-option{display:inline-block;padding:4px 8px;border-radius:12px;font-size:var(--grid-font-size-body, 12px);font-weight:500;white-space:nowrap;line-height:1.2}\n"] }]
|
|
8747
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if(isActive()) {\n <mat-form-field \n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"tag-form-field\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"tag-container\">\n <mat-select\n [placeholder]=\"getProperty('placeholder') || ''\"\n [multiple]=\"true\"\n [disabled]=\"getProperty('disabled') || !isEditable()\"\n [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\"\n [compareWith]=\"compareWith\"\n panelClass=\"tag-panel\"\n (selectionChange)=\"onValueChange($event.value)\"\n (blur)=\"onBlur($event)\"\n (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n \n <mat-option disabled class=\"search-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n @if (isSearchable()) {\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"search-input\"\n [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n }\n <div class=\"select-all-container mat-mdc-option mdc-list-item\"\n [class.mdc-list-item--selected]=\"isAllSelected() || isIndeterminate()\"\n [class.select-all-partial]=\"isIndeterminate()\"\n (click)=\"toggleSelectAll(!isAllSelected()); $event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-pseudo-checkbox\n class=\"mat-mdc-option-pseudo-checkbox select-all-checkbox\"\n [state]=\"isIndeterminate() ? 'indeterminate' : (isAllSelected() ? 'checked' : 'unchecked')\"></mat-pseudo-checkbox>\n <span class=\"mdc-list-item__primary-text select-all-text\">Select All</span>\n </div>\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\" \n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\" \n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"tag-option\" \n [style.background]=\"getTagColor(option.value).background\" \n [style.color]=\"getTagColor(option.value).color\">\n {{ option.label }}\n </span>\n </mat-option>\n }\n\n <mat-option class=\"add-tag-option\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"add-tag-container\" (click)=\"$event.stopPropagation()\">\n <mat-form-field\n [appearance]=\"getProperty('appearance') || 'outline'\"\n class=\"add-tag-form-field\">\n <mat-label>Add new tag</mat-label>\n <input\n matInput\n type=\"text\"\n class=\"add-tag-input\"\n [value]=\"newTagInput()\"\n (input)=\"onNewTagInputChange($any($event.target).value)\"\n (keydown.enter)=\"addNewTag()\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n <div class=\"add-tag-actions\">\n <input\n type=\"color\"\n class=\"add-tag-color-picker\"\n [value]=\"newTagColor()\"\n (input)=\"onNewTagColorChange($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n title=\"Select tag color\">\n <button\n mat-icon-button\n class=\"add-tag-button\"\n [disabled]=\"!canAddNewTag()\"\n (click)=\"addNewTag(); $event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </div>\n </mat-option>\n\n </mat-select>\n </div>\n </mat-form-field>\n} @else {\n <div \n class=\"tag-display\" \n [class.tag-display-editable]=\"isEditable()\"\n (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n @for (tag of tagDisplay().displayTags; track tag) {\n <span class=\"tag\" \n [style.background]=\"getTagColor(tag).background\" \n [style.color]=\"getTagColor(tag).color\">\n {{tag}}\n </span>\n }\n @if(tagDisplay().moreCount > 0) {\n <span class=\"tag\">\n + {{tagDisplay().moreCount}}\n </span>\n }\n </span>\n } @else {\n @for (tag of tagDisplay().displayTags; track tag) {\n <span class=\"tag\" \n [style.background]=\"getTagColor(tag).background\" \n [style.color]=\"getTagColor(tag).color\">\n {{tag}}\n </span>\n }\n @if(tagDisplay().moreCount > 0) {\n <span class=\"tag-more\">\n + {{tagDisplay().moreCount}}\n </span>\n }\n }\n </div>\n}\n\n", styles: [".tag-form-field{width:100%}.tag-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.tag-container{width:100%}.tag-display{width:100%;padding:8px 12px;min-height:30px;display:flex;flex-wrap:wrap;align-items:center;gap:4px;cursor:default}.tag-display.tag-display-editable{cursor:pointer}.tag-display.tag-display-editable:hover{background-color:#0000000a}.tag{display:inline-block;padding:var(--grid-pill-padding-y, 3px) var(--grid-pill-padding-x, 10px);border-radius:var(--grid-pill-radius, 12px);font-size:var(--grid-pill-font-size, var(--grid-font-size-body, 12px));font-weight:var(--grid-pill-font-weight, 500);white-space:nowrap;line-height:1.2}.tag-more{display:inline-block;border-radius:var(--grid-pill-radius, 12px);background-color:var(--grid-surface-container-high, #f5f5f5);color:var(--grid-on-surface-variant, #49454f);font-size:var(--grid-pill-font-size, var(--grid-font-size-body, 12px));font-weight:var(--grid-pill-font-weight, 700);font-style:italic;padding:var(--grid-pill-padding-y, 3px) var(--grid-pill-padding-x, 10px);white-space:nowrap;line-height:1.2}.drillable-value{display:flex;flex-wrap:wrap;gap:4px;align-items:center;cursor:pointer}.drillable-value .tag{text-decoration:underline}.add-option{position:sticky;position:-webkit-sticky;bottom:0;z-index:3;background:var(--grid-surface-container-high, #fff);box-shadow:0 -2px 8px -4px #00000017;border-top:1px solid var(--grid-outline-variant, #e0e0e0)}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important;display:flex!important;flex-direction:column!important;gap:8px!important;opacity:1!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.search-option .select-all-container{padding:4px 0!important;min-height:auto!important;display:flex!important;align-items:center!important;pointer-events:auto!important;cursor:pointer!important;background:transparent!important}.search-option .select-all-container:hover{background:var(--grid-row-hover, rgba(0, 0, 0, .04))!important}.search-option .select-all-container .select-all-text{display:inline-flex!important;flex-direction:row!important;align-items:center!important;width:auto!important;max-width:none!important;gap:0!important;font-family:var(--grid-font-family, \"Poppins\")!important;font-size:var(--grid-font-size-body, 12px)!important;font-weight:500!important;color:var(--grid-on-surface, #1d1b20)!important}.search-option .select-all-container.select-all-partial .select-all-text:before,.search-option .select-all-container.select-all-partial .select-all-checkbox{opacity:.5}.tag-panel-footer{position:absolute;bottom:0;left:0;right:0;background:#fff;border-top:1px solid rgba(0,0,0,.12);padding:8px;z-index:10;box-shadow:0 -2px 4px #0000001a}.tag-panel-footer .add-tag-container{display:flex;align-items:center;gap:8px;width:100%;pointer-events:auto}.tag-panel-footer .add-tag-form-field-wrapper{flex:1;min-width:0;position:relative}.tag-panel-footer .new-tag-input{width:100%;border:1px solid rgba(0,0,0,.38);border-radius:4px;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 12px;font-family:var(--grid-font-family, \"Poppins\")!important;box-sizing:border-box;cursor:text}.tag-panel-footer .new-tag-input:focus{border-color:var(--grid-primary, #6750a4);border-width:2px}.tag-panel-footer .add-tag-button{flex-shrink:0;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 16px!important;min-width:auto!important;pointer-events:auto!important;background-color:var(--grid-primary, #6750a4);color:#fff;border:none;border-radius:4px;cursor:pointer;font-family:var(--grid-font-family, \"Poppins\")!important}.tag-panel-footer .add-tag-button:hover:not([disabled]){opacity:.9}.tag-panel-footer .add-tag-button[disabled]{opacity:.5;cursor:not-allowed}.cdk-overlay-pane.tag-panel-overlay{position:relative;padding-bottom:60px!important}.cdk-overlay-pane.tag-panel-overlay .mat-mdc-select-panel{max-height:calc(100% - 60px)!important}.add-tag-option{position:sticky!important;background:var(--grid-surface, #fff)!important;bottom:-10px!important;z-index:10!important;padding:8px 8px 10px!important;margin-top:auto!important;margin-bottom:0!important;box-shadow:0 -2px 8px #00000026!important;border-top:1px solid rgba(0,0,0,.12)!important}.add-tag-option:hover{background:var(--grid-surface, #fff)!important}.add-tag-option .mat-mdc-option{min-height:auto!important;padding:0!important;height:auto!important}.add-tag-option .mat-mdc-option:hover{background:var(--grid-surface, #fff)!important}.add-tag-option .mdc-list-item__primary-text{width:100%!important;padding:0!important;margin:0!important}.add-tag-option .add-tag-container{display:flex;align-items:center;gap:8px;width:100%;padding:0;margin-bottom:0}.add-tag-option .add-tag-form-field{flex:1;min-width:0}.add-tag-option .add-tag-form-field .mat-mdc-form-field-focus-overlay{background:transparent!important}.add-tag-option .add-tag-form-field .mdc-notched-outline__leading,.add-tag-option .add-tag-form-field .mdc-notched-outline__notch,.add-tag-option .add-tag-form-field .mdc-notched-outline__trailing{border-color:var(--grid-outline-variant, #cac4d0)!important;border-width:1px!important}.add-tag-option .add-tag-form-field.mat-focused .mdc-notched-outline__leading,.add-tag-option .add-tag-form-field.mat-focused .mdc-notched-outline__notch,.add-tag-option .add-tag-form-field.mat-focused .mdc-notched-outline__trailing{border-color:var(--grid-outline, #79747e)!important}.add-tag-option .add-tag-form-field .mdc-floating-label,.add-tag-option .add-tag-form-field label{color:var(--grid-on-surface-variant, #49454f)!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.add-tag-option .add-tag-form-field .mat-mdc-text-field-wrapper{background:transparent!important;padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-infix{min-height:auto!important;padding:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.add-tag-option .add-tag-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.add-tag-option .add-tag-actions{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;flex-shrink:0}.add-tag-option .add-tag-color-picker{flex-shrink:0;width:20px;height:20px;border:1px solid rgba(0,0,0,.12);border-radius:4px;cursor:pointer;padding:2px;background:transparent;box-sizing:border-box;margin:0 auto}.add-tag-option .add-tag-color-picker::-webkit-color-swatch-wrapper{padding:0}.add-tag-option .add-tag-color-picker::-webkit-color-swatch{border:none;border-radius:2px}.add-tag-option .add-tag-color-picker::-moz-color-swatch{border:none;border-radius:2px}.add-tag-option .add-tag-color-picker:hover{border-color:var(--grid-primary, #6750a4)}.add-tag-option .add-tag-color-picker:focus{outline:2px solid var(--grid-primary, #6750a4);outline-offset:2px}.add-tag-option .add-tag-button{flex-shrink:0;width:20px;height:20px;color:var(--grid-primary, #6750a4)!important;display:flex!important;align-items:center!important;justify-content:center!important;margin:0 auto}.add-tag-option .add-tag-button:not([disabled]){color:var(--grid-primary, #6750a4)!important}.add-tag-option .add-tag-button:not([disabled]):hover{background-color:#6750a414!important}.add-tag-option .add-tag-button[disabled]{opacity:.38;color:#00000061!important}.add-tag-option .add-tag-button mat-icon{font-size:24px;width:24px;height:24px;line-height:24px;display:flex;align-items:center;justify-content:center;margin-right:0}.tag-panel .search-option>mat-pseudo-checkbox,.tag-panel .search-option>.mat-mdc-option-pseudo-checkbox,.tag-panel .add-tag-option>mat-pseudo-checkbox,.tag-panel .add-tag-option>.mat-mdc-option-pseudo-checkbox{display:none!important}.tag-panel{min-width:200px!important}.tag-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.tag-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.tag-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important;display:flex!important;align-items:center!important}mat-option .tag-option{display:inline-block;padding:4px 8px;border-radius:12px;font-size:var(--grid-font-size-body, 12px);font-weight:500;white-space:nowrap;line-height:1.2}\n"] }]
|
|
8743
8748
|
}], ctorParameters: () => [], propDecorators: { selectContainer: [{
|
|
8744
8749
|
type: ViewChild,
|
|
8745
8750
|
args: ['selectContainer', { static: false }]
|
|
@@ -9132,7 +9137,7 @@ class PeopleComponent {
|
|
|
9132
9137
|
return `${option?.value || ''}_${index}`;
|
|
9133
9138
|
}
|
|
9134
9139
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: PeopleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9135
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: PeopleComponent, isStandalone: true, selector: "eru-people", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null }, personCardTemplate: { classPropertyName: "personCardTemplate", publicName: "personCardTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n<mat-form-field appearance=\"outline\" class=\"people-form-field\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"people-select-container\">\n <mat-select [multiple]=\"isMultiple()\" [disabled]=\"!isEditable()\" [value]=\"selectValue()\" panelClass=\"people-select-panel\"\n (selectionChange)=\"onSelectionChange($event.value)\" (blur)=\"onBlur($event)\" (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n\n <mat-select-trigger>\n <div class=\"people-trigger-content\">\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\" [style.z-index]=\"currentValue().length - $index\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">Select people...</span>\n }\n </div>\n </mat-select-trigger>\n\n @if (isSearchable() || isMultiple()) {\n <mat-option disabled class=\"search-option\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n @if (isSearchable()) {\n <mat-form-field appearance=\"outline\" class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input matInput type=\"text\" class=\"search-input\" placeholder=\"filter options...\" [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n }\n @if (isMultiple()) {\n <div class=\"select-all-container\" (click)=\"$event.stopPropagation()\">\n <mat-checkbox [checked]=\"isAllSelected()\" [indeterminate]=\"isIndeterminate()\"\n (change)=\"toggleSelectAll($event.checked)\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"select-all-text\">Select All</span>\n </mat-checkbox>\n </div>\n }\n </mat-option>\n }\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\" (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"option-content\">\n <div class=\"option-avatar\">{{ getInitials(option.label) }}</div>\n <span class=\"option-text\">{{ option.label }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </div>\n</mat-form-field>\n} @else {\n<div class=\"people-display\" [class.people-display-editable]=\"isEditable()\" (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"people-drillable\" (click)=\"onDrillableClick($event)\">\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\" [style.z-index]=\"currentValue().length - $index\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">No people assigned</span>\n }\n </span>\n } @else {\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\"\n [style.z-index]=\"currentValue().length - $index\"\n [class.avatar-card-trigger]=\"cardEnabled()\"\n cdkOverlayOrigin\n #cardOrigin=\"cdkOverlayOrigin\"\n (mouseenter)=\"onAvatarEnter(assigneeId)\"\n (mouseleave)=\"onAvatarLeave()\"\n (click)=\"onAvatarCardClick($event, assigneeId)\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n\n <!-- Card content comes from the consumer; the grid owns trigger and\n placement. Beside the avatar first, dropping below only if neither\n side fits. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"cardOrigin\"\n [cdkConnectedOverlayOpen]=\"cardEnabled() && openCardUserId() === assigneeId\"\n [cdkConnectedOverlayPositions]=\"cardPositions\"\n (overlayOutsideClick)=\"closeCard()\"\n (detach)=\"closeCard()\">\n <div class=\"people-card-overlay\"\n (mouseenter)=\"onAvatarEnter(assigneeId)\"\n (mouseleave)=\"onAvatarLeave()\">\n <ng-container\n *ngTemplateOutlet=\"personCardTemplate()!;\n context: { $implicit: assigneeId, column: config(), cardPage: cardPage() }\">\n </ng-container>\n </div>\n </ng-template>\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">No people assigned</span>\n }\n }\n</div>\n}", styles: [".people-form-field{width:100%!important;height:100%!important;padding:2px!important;margin:0!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;line-height:normal!important;box-sizing:border-box!important;max-width:none!important;min-width:0!important;flex:none!important}.people-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.people-select-container{width:100%;display:flex;align-items:center}.people-trigger-content{display:flex;align-items:center;gap:4px;padding:4px;min-height:32px;width:100%;overflow:hidden;flex-wrap:nowrap}.people-display{display:flex;align-items:center;gap:4px;padding:4px;min-height:32px;width:100%;height:100%;cursor:default;overflow:hidden;flex-wrap:nowrap}.people-display.people-display-editable{cursor:pointer}.people-display.people-display-editable:hover{background-color:#0000000a}.avatar-circle{width:var(--grid-avatar-size, 28px);height:var(--grid-avatar-size, 28px);min-width:var(--grid-avatar-size, 28px);min-height:var(--grid-avatar-size, 28px);max-width:var(--grid-avatar-size, 28px);max-height:var(--grid-avatar-size, 28px);border-radius:50%;background-color:var(--grid-primary, #6750a4);color:#fff;display:flex;align-items:center;justify-content:center;font-size:var(--grid-avatar-font-size, 10px);font-weight:var(--grid-avatar-font-weight, 500);border:2px solid var(--grid-surface, #fef7ff);margin-left:-8px;position:relative;z-index:1;flex-shrink:0;box-sizing:border-box}.avatar-circle:first-child{margin-left:0}.avatar-circle.count-circle{background-color:var(--grid-surface-variant, #e7e0ec);color:var(--grid-on-surface-variant, #49454f);font-size:var(--grid-avatar-font-size, 11px);font-weight:var(--grid-avatar-font-weight, 500)}.no-people-text{color:var(--grid-on-surface-variant, #49454f);font-style:italic;font-size:12px;padding:4px 8px}.people-drillable{display:flex;align-items:center;gap:4px;cursor:pointer;color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease}.people-drillable .avatar-circle{text-decoration:none}.people-select-panel{min-width:200px!important}.people-select-panel .search-option{height:auto!important;padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.people-select-panel .search-option .mdc-list-item__primary-text{opacity:1!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto;box-sizing:border-box!important;margin-bottom:8px}.people-select-panel .search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.people-select-panel .search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .select-all-container{padding:4px 8px;cursor:pointer;pointer-events:auto}.people-select-panel .search-option .select-all-container .select-all-text{margin-left:8px;font-size:var(--grid-font-size-body, 12px)}.people-select-panel .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.people-select-panel .mat-mdc-option{padding:8px 12px;cursor:pointer;transition:background-color .2s}.people-select-panel .mat-mdc-option:hover{background-color:#0000000a}.people-select-panel .mat-mdc-option[aria-selected=true]{background-color:#6750a41a}.option-content{display:flex;align-items:center;gap:8px;width:100%}.option-avatar{width:24px;height:24px;border-radius:50%;background-color:var(--grid-primary, #6750a4);color:#fff;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;flex-shrink:0}.option-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.checkmark{color:var(--grid-primary, #6750a4);font-weight:700;font-size:14px;flex-shrink:0}.people-card-overlay{background:var(--eru-grid-surface, #ffffff);border:1px solid var(--eru-grid-divider, #e5e7eb);border-radius:10px;box-shadow:0 8px 24px -8px #00000040;overflow:hidden}.avatar-card-trigger{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$3.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$3.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i2$2.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9140
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: PeopleComponent, isStandalone: true, selector: "eru-people", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null }, personCardTemplate: { classPropertyName: "personCardTemplate", publicName: "personCardTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n<mat-form-field appearance=\"outline\" class=\"people-form-field\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"people-select-container\">\n <mat-select [multiple]=\"isMultiple()\" [disabled]=\"!isEditable()\" [value]=\"selectValue()\" panelClass=\"people-select-panel\"\n (selectionChange)=\"onSelectionChange($event.value)\" (blur)=\"onBlur($event)\" (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n\n <mat-select-trigger>\n <div class=\"people-trigger-content\">\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\" [style.z-index]=\"currentValue().length - $index\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">Select people...</span>\n }\n </div>\n </mat-select-trigger>\n\n @if (isSearchable() || isMultiple()) {\n <mat-option disabled class=\"search-option\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n @if (isSearchable()) {\n <mat-form-field appearance=\"outline\" class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input matInput type=\"text\" class=\"search-input\" [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n }\n @if (isMultiple()) {\n <div class=\"select-all-container\" (click)=\"$event.stopPropagation()\">\n <mat-checkbox [checked]=\"isAllSelected()\" [indeterminate]=\"isIndeterminate()\"\n (change)=\"toggleSelectAll($event.checked)\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"select-all-text\">Select All</span>\n </mat-checkbox>\n </div>\n }\n </mat-option>\n }\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\" (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"option-content\">\n <div class=\"option-avatar\">{{ getInitials(option.label) }}</div>\n <span class=\"option-text\">{{ option.label }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </div>\n</mat-form-field>\n} @else {\n<div class=\"people-display\" [class.people-display-editable]=\"isEditable()\" (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"people-drillable\" (click)=\"onDrillableClick($event)\">\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\" [style.z-index]=\"currentValue().length - $index\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">No people assigned</span>\n }\n </span>\n } @else {\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\"\n [style.z-index]=\"currentValue().length - $index\"\n [class.avatar-card-trigger]=\"cardEnabled()\"\n cdkOverlayOrigin\n #cardOrigin=\"cdkOverlayOrigin\"\n (mouseenter)=\"onAvatarEnter(assigneeId)\"\n (mouseleave)=\"onAvatarLeave()\"\n (click)=\"onAvatarCardClick($event, assigneeId)\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n\n <!-- Card content comes from the consumer; the grid owns trigger and\n placement. Beside the avatar first, dropping below only if neither\n side fits. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"cardOrigin\"\n [cdkConnectedOverlayOpen]=\"cardEnabled() && openCardUserId() === assigneeId\"\n [cdkConnectedOverlayPositions]=\"cardPositions\"\n (overlayOutsideClick)=\"closeCard()\"\n (detach)=\"closeCard()\">\n <div class=\"people-card-overlay\"\n (mouseenter)=\"onAvatarEnter(assigneeId)\"\n (mouseleave)=\"onAvatarLeave()\">\n <ng-container\n *ngTemplateOutlet=\"personCardTemplate()!;\n context: { $implicit: assigneeId, column: config(), cardPage: cardPage() }\">\n </ng-container>\n </div>\n </ng-template>\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">No people assigned</span>\n }\n }\n</div>\n}", styles: [".people-form-field{width:100%!important;height:100%!important;padding:2px!important;margin:0!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;line-height:normal!important;box-sizing:border-box!important;max-width:none!important;min-width:0!important;flex:none!important}.people-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.people-select-container{width:100%;display:flex;align-items:center}.people-trigger-content{display:flex;align-items:center;gap:4px;padding:4px;min-height:32px;width:100%;overflow:hidden;flex-wrap:nowrap}.people-display{display:flex;align-items:center;gap:4px;padding:4px;min-height:32px;width:100%;height:100%;cursor:default;overflow:hidden;flex-wrap:nowrap}.people-display.people-display-editable{cursor:pointer}.people-display.people-display-editable:hover{background-color:#0000000a}.avatar-circle{width:var(--grid-avatar-size, 28px);height:var(--grid-avatar-size, 28px);min-width:var(--grid-avatar-size, 28px);min-height:var(--grid-avatar-size, 28px);max-width:var(--grid-avatar-size, 28px);max-height:var(--grid-avatar-size, 28px);border-radius:50%;background-color:var(--grid-primary, #6750a4);color:#fff;display:flex;align-items:center;justify-content:center;font-size:var(--grid-avatar-font-size, 10px);font-weight:var(--grid-avatar-font-weight, 500);border:2px solid var(--grid-surface, #fef7ff);margin-left:-8px;position:relative;z-index:1;flex-shrink:0;box-sizing:border-box}.avatar-circle:first-child{margin-left:0}.avatar-circle.count-circle{background-color:var(--grid-surface-variant, #e7e0ec);color:var(--grid-on-surface-variant, #49454f);font-size:var(--grid-avatar-font-size, 11px);font-weight:var(--grid-avatar-font-weight, 500)}.no-people-text{color:var(--grid-on-surface-variant, #49454f);font-style:italic;font-size:12px;padding:4px 8px}.people-drillable{display:flex;align-items:center;gap:4px;cursor:pointer;color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease}.people-drillable .avatar-circle{text-decoration:none}.people-select-panel{min-width:200px!important}.people-select-panel .search-option{height:auto!important;padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.people-select-panel .search-option .mdc-list-item__primary-text{opacity:1!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto;box-sizing:border-box!important;margin-bottom:8px}.people-select-panel .search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.people-select-panel .search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .select-all-container{padding:4px 8px;cursor:pointer;pointer-events:auto}.people-select-panel .search-option .select-all-container .select-all-text{margin-left:8px;font-size:var(--grid-font-size-body, 12px)}.people-select-panel .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.people-select-panel .mat-mdc-option{padding:8px 12px;cursor:pointer;transition:background-color .2s}.people-select-panel .mat-mdc-option:hover{background-color:#0000000a}.people-select-panel .mat-mdc-option[aria-selected=true]{background-color:#6750a41a}.option-content{display:flex;align-items:center;gap:8px;width:100%}.option-avatar{width:24px;height:24px;border-radius:50%;background-color:var(--grid-primary, #6750a4);color:#fff;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;flex-shrink:0}.option-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.checkmark{color:var(--grid-primary, #6750a4);font-weight:700;font-size:14px;flex-shrink:0}.people-card-overlay{background:var(--eru-grid-surface, #ffffff);border:1px solid var(--eru-grid-divider, #e5e7eb);border-radius:10px;box-shadow:0 8px 24px -8px #00000040;overflow:hidden}.avatar-card-trigger{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$3.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$3.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i2$3.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i2$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9136
9141
|
}
|
|
9137
9142
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: PeopleComponent, decorators: [{
|
|
9138
9143
|
type: Component,
|
|
@@ -9145,7 +9150,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
9145
9150
|
MatSelectModule,
|
|
9146
9151
|
MatOptionModule,
|
|
9147
9152
|
MatCheckboxModule
|
|
9148
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if(isActive()) {\n<mat-form-field appearance=\"outline\" class=\"people-form-field\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"people-select-container\">\n <mat-select [multiple]=\"isMultiple()\" [disabled]=\"!isEditable()\" [value]=\"selectValue()\" panelClass=\"people-select-panel\"\n (selectionChange)=\"onSelectionChange($event.value)\" (blur)=\"onBlur($event)\" (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n\n <mat-select-trigger>\n <div class=\"people-trigger-content\">\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\" [style.z-index]=\"currentValue().length - $index\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">Select people...</span>\n }\n </div>\n </mat-select-trigger>\n\n @if (isSearchable() || isMultiple()) {\n <mat-option disabled class=\"search-option\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n @if (isSearchable()) {\n <mat-form-field appearance=\"outline\" class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input matInput type=\"text\" class=\"search-input\" placeholder=\"filter options...\" [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n }\n @if (isMultiple()) {\n <div class=\"select-all-container\" (click)=\"$event.stopPropagation()\">\n <mat-checkbox [checked]=\"isAllSelected()\" [indeterminate]=\"isIndeterminate()\"\n (change)=\"toggleSelectAll($event.checked)\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"select-all-text\">Select All</span>\n </mat-checkbox>\n </div>\n }\n </mat-option>\n }\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\" (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"option-content\">\n <div class=\"option-avatar\">{{ getInitials(option.label) }}</div>\n <span class=\"option-text\">{{ option.label }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </div>\n</mat-form-field>\n} @else {\n<div class=\"people-display\" [class.people-display-editable]=\"isEditable()\" (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"people-drillable\" (click)=\"onDrillableClick($event)\">\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\" [style.z-index]=\"currentValue().length - $index\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">No people assigned</span>\n }\n </span>\n } @else {\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\"\n [style.z-index]=\"currentValue().length - $index\"\n [class.avatar-card-trigger]=\"cardEnabled()\"\n cdkOverlayOrigin\n #cardOrigin=\"cdkOverlayOrigin\"\n (mouseenter)=\"onAvatarEnter(assigneeId)\"\n (mouseleave)=\"onAvatarLeave()\"\n (click)=\"onAvatarCardClick($event, assigneeId)\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n\n <!-- Card content comes from the consumer; the grid owns trigger and\n placement. Beside the avatar first, dropping below only if neither\n side fits. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"cardOrigin\"\n [cdkConnectedOverlayOpen]=\"cardEnabled() && openCardUserId() === assigneeId\"\n [cdkConnectedOverlayPositions]=\"cardPositions\"\n (overlayOutsideClick)=\"closeCard()\"\n (detach)=\"closeCard()\">\n <div class=\"people-card-overlay\"\n (mouseenter)=\"onAvatarEnter(assigneeId)\"\n (mouseleave)=\"onAvatarLeave()\">\n <ng-container\n *ngTemplateOutlet=\"personCardTemplate()!;\n context: { $implicit: assigneeId, column: config(), cardPage: cardPage() }\">\n </ng-container>\n </div>\n </ng-template>\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">No people assigned</span>\n }\n }\n</div>\n}", styles: [".people-form-field{width:100%!important;height:100%!important;padding:2px!important;margin:0!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;line-height:normal!important;box-sizing:border-box!important;max-width:none!important;min-width:0!important;flex:none!important}.people-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.people-select-container{width:100%;display:flex;align-items:center}.people-trigger-content{display:flex;align-items:center;gap:4px;padding:4px;min-height:32px;width:100%;overflow:hidden;flex-wrap:nowrap}.people-display{display:flex;align-items:center;gap:4px;padding:4px;min-height:32px;width:100%;height:100%;cursor:default;overflow:hidden;flex-wrap:nowrap}.people-display.people-display-editable{cursor:pointer}.people-display.people-display-editable:hover{background-color:#0000000a}.avatar-circle{width:var(--grid-avatar-size, 28px);height:var(--grid-avatar-size, 28px);min-width:var(--grid-avatar-size, 28px);min-height:var(--grid-avatar-size, 28px);max-width:var(--grid-avatar-size, 28px);max-height:var(--grid-avatar-size, 28px);border-radius:50%;background-color:var(--grid-primary, #6750a4);color:#fff;display:flex;align-items:center;justify-content:center;font-size:var(--grid-avatar-font-size, 10px);font-weight:var(--grid-avatar-font-weight, 500);border:2px solid var(--grid-surface, #fef7ff);margin-left:-8px;position:relative;z-index:1;flex-shrink:0;box-sizing:border-box}.avatar-circle:first-child{margin-left:0}.avatar-circle.count-circle{background-color:var(--grid-surface-variant, #e7e0ec);color:var(--grid-on-surface-variant, #49454f);font-size:var(--grid-avatar-font-size, 11px);font-weight:var(--grid-avatar-font-weight, 500)}.no-people-text{color:var(--grid-on-surface-variant, #49454f);font-style:italic;font-size:12px;padding:4px 8px}.people-drillable{display:flex;align-items:center;gap:4px;cursor:pointer;color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease}.people-drillable .avatar-circle{text-decoration:none}.people-select-panel{min-width:200px!important}.people-select-panel .search-option{height:auto!important;padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.people-select-panel .search-option .mdc-list-item__primary-text{opacity:1!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto;box-sizing:border-box!important;margin-bottom:8px}.people-select-panel .search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.people-select-panel .search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .select-all-container{padding:4px 8px;cursor:pointer;pointer-events:auto}.people-select-panel .search-option .select-all-container .select-all-text{margin-left:8px;font-size:var(--grid-font-size-body, 12px)}.people-select-panel .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.people-select-panel .mat-mdc-option{padding:8px 12px;cursor:pointer;transition:background-color .2s}.people-select-panel .mat-mdc-option:hover{background-color:#0000000a}.people-select-panel .mat-mdc-option[aria-selected=true]{background-color:#6750a41a}.option-content{display:flex;align-items:center;gap:8px;width:100%}.option-avatar{width:24px;height:24px;border-radius:50%;background-color:var(--grid-primary, #6750a4);color:#fff;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;flex-shrink:0}.option-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.checkmark{color:var(--grid-primary, #6750a4);font-weight:700;font-size:14px;flex-shrink:0}.people-card-overlay{background:var(--eru-grid-surface, #ffffff);border:1px solid var(--eru-grid-divider, #e5e7eb);border-radius:10px;box-shadow:0 8px 24px -8px #00000040;overflow:hidden}.avatar-card-trigger{cursor:pointer}\n"] }]
|
|
9153
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "@if(isActive()) {\n<mat-form-field appearance=\"outline\" class=\"people-form-field\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"people-select-container\">\n <mat-select [multiple]=\"isMultiple()\" [disabled]=\"!isEditable()\" [value]=\"selectValue()\" panelClass=\"people-select-panel\"\n (selectionChange)=\"onSelectionChange($event.value)\" (blur)=\"onBlur($event)\" (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n\n <mat-select-trigger>\n <div class=\"people-trigger-content\">\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\" [style.z-index]=\"currentValue().length - $index\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">Select people...</span>\n }\n </div>\n </mat-select-trigger>\n\n @if (isSearchable() || isMultiple()) {\n <mat-option disabled class=\"search-option\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n @if (isSearchable()) {\n <mat-form-field appearance=\"outline\" class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input matInput type=\"text\" class=\"search-input\" [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n }\n @if (isMultiple()) {\n <div class=\"select-all-container\" (click)=\"$event.stopPropagation()\">\n <mat-checkbox [checked]=\"isAllSelected()\" [indeterminate]=\"isIndeterminate()\"\n (change)=\"toggleSelectAll($event.checked)\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <span class=\"select-all-text\">Select All</span>\n </mat-checkbox>\n </div>\n }\n </mat-option>\n }\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\" (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\"\n (click)=\"$event.stopPropagation(); $event.preventDefault()\">\n <div class=\"option-content\">\n <div class=\"option-avatar\">{{ getInitials(option.label) }}</div>\n <span class=\"option-text\">{{ option.label }}</span>\n </div>\n </mat-option>\n }\n </mat-select>\n </div>\n</mat-form-field>\n} @else {\n<div class=\"people-display\" [class.people-display-editable]=\"isEditable()\" (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"people-drillable\" (click)=\"onDrillableClick($event)\">\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\" [style.z-index]=\"currentValue().length - $index\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">No people assigned</span>\n }\n </span>\n } @else {\n @if (isAssigneeArray(currentValue()) && currentValue().length > 0) {\n @for (assigneeId of displayAvatars(); track assigneeId) {\n <div class=\"avatar-circle\"\n [style.z-index]=\"currentValue().length - $index\"\n [class.avatar-card-trigger]=\"cardEnabled()\"\n cdkOverlayOrigin\n #cardOrigin=\"cdkOverlayOrigin\"\n (mouseenter)=\"onAvatarEnter(assigneeId)\"\n (mouseleave)=\"onAvatarLeave()\"\n (click)=\"onAvatarCardClick($event, assigneeId)\">\n {{ getInitials(getDisplayName(assigneeId)) }}\n\n <!-- Card content comes from the consumer; the grid owns trigger and\n placement. Beside the avatar first, dropping below only if neither\n side fits. -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"cardOrigin\"\n [cdkConnectedOverlayOpen]=\"cardEnabled() && openCardUserId() === assigneeId\"\n [cdkConnectedOverlayPositions]=\"cardPositions\"\n (overlayOutsideClick)=\"closeCard()\"\n (detach)=\"closeCard()\">\n <div class=\"people-card-overlay\"\n (mouseenter)=\"onAvatarEnter(assigneeId)\"\n (mouseleave)=\"onAvatarLeave()\">\n <ng-container\n *ngTemplateOutlet=\"personCardTemplate()!;\n context: { $implicit: assigneeId, column: config(), cardPage: cardPage() }\">\n </ng-container>\n </div>\n </ng-template>\n </div>\n }\n @if (remainingCount() > 0) {\n <div class=\"avatar-circle count-circle\" [style.z-index]=\"1\">\n +{{ remainingCount() }}\n </div>\n }\n } @else {\n <span class=\"no-people-text\">No people assigned</span>\n }\n }\n</div>\n}", styles: [".people-form-field{width:100%!important;height:100%!important;padding:2px!important;margin:0!important;border:none!important;outline:none!important;background:transparent!important;font-size:var(--grid-font-size-body, 12px)!important;line-height:normal!important;box-sizing:border-box!important;max-width:none!important;min-width:0!important;flex:none!important}.people-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.people-select-container{width:100%;display:flex;align-items:center}.people-trigger-content{display:flex;align-items:center;gap:4px;padding:4px;min-height:32px;width:100%;overflow:hidden;flex-wrap:nowrap}.people-display{display:flex;align-items:center;gap:4px;padding:4px;min-height:32px;width:100%;height:100%;cursor:default;overflow:hidden;flex-wrap:nowrap}.people-display.people-display-editable{cursor:pointer}.people-display.people-display-editable:hover{background-color:#0000000a}.avatar-circle{width:var(--grid-avatar-size, 28px);height:var(--grid-avatar-size, 28px);min-width:var(--grid-avatar-size, 28px);min-height:var(--grid-avatar-size, 28px);max-width:var(--grid-avatar-size, 28px);max-height:var(--grid-avatar-size, 28px);border-radius:50%;background-color:var(--grid-primary, #6750a4);color:#fff;display:flex;align-items:center;justify-content:center;font-size:var(--grid-avatar-font-size, 10px);font-weight:var(--grid-avatar-font-weight, 500);border:2px solid var(--grid-surface, #fef7ff);margin-left:-8px;position:relative;z-index:1;flex-shrink:0;box-sizing:border-box}.avatar-circle:first-child{margin-left:0}.avatar-circle.count-circle{background-color:var(--grid-surface-variant, #e7e0ec);color:var(--grid-on-surface-variant, #49454f);font-size:var(--grid-avatar-font-size, 11px);font-weight:var(--grid-avatar-font-weight, 500)}.no-people-text{color:var(--grid-on-surface-variant, #49454f);font-style:italic;font-size:12px;padding:4px 8px}.people-drillable{display:flex;align-items:center;gap:4px;cursor:pointer;color:var(--grid-primary, #6750a4);text-decoration:underline;text-decoration-color:var(--grid-primary, #6750a4);text-decoration-thickness:1px;text-underline-offset:2px;transition:all .2s ease}.people-drillable .avatar-circle{text-decoration:none}.people-select-panel{min-width:200px!important}.people-select-panel .search-option{height:auto!important;padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.people-select-panel .search-option .mdc-list-item__primary-text{opacity:1!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto;box-sizing:border-box!important;margin-bottom:8px}.people-select-panel .search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.people-select-panel .search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.people-select-panel .search-option .select-all-container{padding:4px 8px;cursor:pointer;pointer-events:auto}.people-select-panel .search-option .select-all-container .select-all-text{margin-left:8px;font-size:var(--grid-font-size-body, 12px)}.people-select-panel .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.people-select-panel .mat-mdc-option{padding:8px 12px;cursor:pointer;transition:background-color .2s}.people-select-panel .mat-mdc-option:hover{background-color:#0000000a}.people-select-panel .mat-mdc-option[aria-selected=true]{background-color:#6750a41a}.option-content{display:flex;align-items:center;gap:8px;width:100%}.option-avatar{width:24px;height:24px;border-radius:50%;background-color:var(--grid-primary, #6750a4);color:#fff;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;flex-shrink:0}.option-text{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.checkmark{color:var(--grid-primary, #6750a4);font-weight:700;font-size:14px;flex-shrink:0}.people-card-overlay{background:var(--eru-grid-surface, #ffffff);border:1px solid var(--eru-grid-divider, #e5e7eb);border-radius:10px;box-shadow:0 8px 24px -8px #00000040;overflow:hidden}.avatar-card-trigger{cursor:pointer}\n"] }]
|
|
9149
9154
|
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], isEditable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEditable", required: false }] }], isActive: [{ type: i0.Input, args: [{ isSignal: true, alias: "isActive", required: false }] }], isDrillable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDrillable", required: false }] }], columnWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "columnWidth", required: false }] }], eruGridStore: [{ type: i0.Input, args: [{ isSignal: true, alias: "eruGridStore", required: false }] }], personCardTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "personCardTemplate", required: false }] }], valueChange: [{
|
|
9150
9155
|
type: Output
|
|
9151
9156
|
}], blur: [{
|
|
@@ -9374,7 +9379,7 @@ class PriorityComponent {
|
|
|
9374
9379
|
return `${option.value}_${index}`;
|
|
9375
9380
|
}
|
|
9376
9381
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: PriorityComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9377
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: PriorityComponent, isStandalone: true, selector: "eru-priority", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }, { propertyName: "matSelect", first: true, predicate: ["matSelect"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n<mat-form-field [appearance]=\"getProperty('appearance') || 'outline'\" class=\"priority-form-field\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"priority-container\">\n <mat-select #matSelect [placeholder]=\"getProperty('placeholder') || ''\" [multiple]=\"false\"\n [disabled]=\"getProperty('disabled') || !isEditable()\" [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\" [compareWith]=\"compareWith\" panelClass=\"priority-panel\"\n (selectionChange)=\"onValueChange($event.value)\" (blur)=\"onBlur($event)\" (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n\n <mat-select-trigger>\n @if(priorityIcon()) {\n <span class=\"priority-trigger\">\n <mat-icon class=\"priority-icon-trigger\" [style.color]=\"priorityColor()\">flag</mat-icon>\n <span>{{ getSelectedLabel() }}</span>\n </span>\n } @else {\n <span>{{ getSelectedLabel() }}</span>\n }\n </mat-select-trigger>\n\n <mat-option disabled class=\"search-option\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-form-field [appearance]=\"getProperty('appearance') || 'outline'\" class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input matInput type=\"text\" class=\"search-input\" [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\">\n <span class=\"priority-option\">\n <mat-icon class=\"priority-icon\" [style.color]=\"getOptionColor(option)\">flag</mat-icon>\n <span class=\"priority-label\">{{ option.label }}</span>\n </span>\n </mat-option>\n }\n </mat-select>\n </div>\n</mat-form-field>\n} @else {\n<div class=\"priority-display\" [class.priority-display-editable]=\"isEditable()\" (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n @if(priorityIcon()) {\n <span class=\"priority-dot\" [style.background-color]=\"priorityColor()\"></span>\n }\n <span class=\"priority-label-text\">{{getSelectedLabel()}}</span>\n </span>\n } @else {\n @if(priorityIcon()) {\n <span class=\"priority-dot\" [style.background-color]=\"priorityColor()\"></span>\n }\n <span class=\"priority-label-text\">{{getSelectedLabel()}}</span>\n }\n</div>\n}", styles: [".priority-form-field{width:100%}.priority-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.priority-container{width:100%}.priority-trigger{display:flex;align-items:center;gap:8px;width:100%}.priority-icon-trigger{width:16px;height:16px;padding-left:2px;font-size:16px;line-height:16px;flex-shrink:0}.priority-display{width:100%;padding:8px 12px;min-height:30px;display:flex;align-items:center;gap:8px;cursor:default}.priority-display.priority-display-editable{cursor:pointer}.priority-display.priority-display-editable:hover{background-color:#0000000a}.priority-icon-display{width:16px;height:16px;font-size:16px;line-height:16px}.priority-dot{display:inline-block;width:var(--grid-priority-dot-size, 8px);height:var(--grid-priority-dot-size, 8px);border-radius:50%;flex-shrink:0}.priority-label-text{line-height:1.2}.drillable-value{display:flex;align-items:center;gap:8px;color:#1976d2;cursor:pointer;text-decoration:underline}.drillable-value:hover{color:#1565c0}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.priority-panel{min-width:150px!important}.priority-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.priority-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.priority-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}.mat-select-panel-animations-enabled mat-option:first-of-type mat-pseudo-checkbox{display:none!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important;display:flex!important;align-items:center!important}mat-option .priority-option{display:flex;align-items:center;gap:8px;width:100%}mat-option .priority-icon{width:16px;height:16px;font-size:16px;line-height:16px;flex-shrink:0}mat-option .priority-label{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$
|
|
9382
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: PriorityComponent, isStandalone: true, selector: "eru-priority", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, fieldSize: { classPropertyName: "fieldSize", publicName: "fieldSize", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "selectContainer", first: true, predicate: ["selectContainer"], descendants: true }, { propertyName: "matSelect", first: true, predicate: ["matSelect"], descendants: true }], ngImport: i0, template: "@if(isActive()) {\n<mat-form-field [appearance]=\"getProperty('appearance') || 'outline'\" class=\"priority-form-field\"\n (click)=\"$event.stopPropagation()\" (mousedown)=\"$event.stopPropagation()\">\n <div #selectContainer class=\"priority-container\">\n <mat-select #matSelect [placeholder]=\"getProperty('placeholder') || ''\" [multiple]=\"false\"\n [disabled]=\"getProperty('disabled') || !isEditable()\" [required]=\"hasRequiredValidation()\"\n [value]=\"currentValue()\" [compareWith]=\"compareWith\" panelClass=\"priority-panel\"\n (selectionChange)=\"onValueChange($event.value)\" (blur)=\"onBlur($event)\" (openedChange)=\"onOpenedChange($event)\"\n (click)=\"$event.stopPropagation()\">\n\n <mat-select-trigger>\n @if(priorityIcon()) {\n <span class=\"priority-trigger\">\n <mat-icon class=\"priority-icon-trigger\" [style.color]=\"priorityColor()\">flag</mat-icon>\n <span>{{ getSelectedLabel() }}</span>\n </span>\n } @else {\n <span>{{ getSelectedLabel() }}</span>\n }\n </mat-select-trigger>\n\n <mat-option disabled class=\"search-option\" (click)=\"$event.stopPropagation(); $event.preventDefault()\"\n (mousedown)=\"$event.stopPropagation(); $event.preventDefault()\">\n <mat-form-field [appearance]=\"getProperty('appearance') || 'outline'\" class=\"search-form-field\">\n <mat-label>Search</mat-label>\n <input matInput type=\"text\" class=\"search-input\" [value]=\"searchText()\"\n (input)=\"onSearchChange($any($event.target).value)\" (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\" (keydown)=\"$event.stopPropagation()\"\n (focus)=\"$event.stopPropagation()\">\n </mat-form-field>\n </mat-option>\n\n @for (option of filteredOptions(); track trackByValueAndIndex($index, option)) {\n <mat-option [value]=\"option.value\">\n <span class=\"priority-option\">\n <mat-icon class=\"priority-icon\" [style.color]=\"getOptionColor(option)\">flag</mat-icon>\n <span class=\"priority-label\">{{ option.label }}</span>\n </span>\n </mat-option>\n }\n </mat-select>\n </div>\n</mat-form-field>\n} @else {\n<div class=\"priority-display\" [class.priority-display-editable]=\"isEditable()\" (dblclick)=\"onActivate()\">\n @if (isDrillable()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n @if(priorityIcon()) {\n <span class=\"priority-dot\" [style.background-color]=\"priorityColor()\"></span>\n }\n <span class=\"priority-label-text\">{{getSelectedLabel()}}</span>\n </span>\n } @else {\n @if(priorityIcon()) {\n <span class=\"priority-dot\" [style.background-color]=\"priorityColor()\"></span>\n }\n <span class=\"priority-label-text\">{{getSelectedLabel()}}</span>\n }\n</div>\n}", styles: [".priority-form-field{width:100%}.priority-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.priority-container{width:100%}.priority-trigger{display:flex;align-items:center;gap:8px;width:100%}.priority-icon-trigger{width:16px;height:16px;padding-left:2px;font-size:16px;line-height:16px;flex-shrink:0}.priority-display{width:100%;padding:8px 12px;min-height:30px;display:flex;align-items:center;gap:8px;cursor:default}.priority-display.priority-display-editable{cursor:pointer}.priority-display.priority-display-editable:hover{background-color:#0000000a}.priority-icon-display{width:16px;height:16px;font-size:16px;line-height:16px}.priority-dot{display:inline-block;width:var(--grid-priority-dot-size, 8px);height:var(--grid-priority-dot-size, 8px);border-radius:50%;flex-shrink:0}.priority-label-text{line-height:1.2}.drillable-value{display:flex;align-items:center;gap:8px;color:#1976d2;cursor:pointer;text-decoration:underline}.drillable-value:hover{color:#1565c0}.search-option{padding:2px 4px!important;cursor:default!important;pointer-events:auto!important;width:100%!important;box-sizing:border-box!important;overflow:hidden!important}.search-option .mat-mdc-option{height:auto!important;padding:2px 4px!important;min-height:auto!important}.search-option .mat-mdc-option:hover{background:transparent!important}.search-option .mdc-list-item__primary-text{width:100%!important;max-width:100%!important;box-sizing:border-box!important;padding:0!important;margin:0!important}.search-option .search-form-field{width:100%!important;max-width:100%!important;pointer-events:auto!important;box-sizing:border-box!important;margin:0!important}.search-option .search-form-field .mat-mdc-form-field-subscript-wrapper{display:none}.search-option .search-form-field .mat-mdc-text-field-wrapper{padding-bottom:0!important;width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-form-field .mat-mdc-form-field-infix{width:100%!important;max-width:100%!important;box-sizing:border-box!important;min-height:auto!important;padding:0!important}.search-option .search-form-field .mat-mdc-form-field-flex{width:100%!important;max-width:100%!important;box-sizing:border-box!important}.search-option .search-input{width:100%;border:none;outline:none;background:transparent;font-size:var(--grid-font-size-body, 12px)!important;padding:8px 0}.priority-panel{min-width:150px!important}.priority-panel .search-option .mat-mdc-option,.mat-mdc-select-panel .search-option .mat-mdc-option{min-height:auto!important;padding:2px 4px!important}.priority-panel .mdc-list-item--disabled,.mat-mdc-select-panel .mdc-list-item--disabled{pointer-events:auto!important;cursor:default!important}.priority-panel .mdc-list-item--disabled:hover,.mat-mdc-select-panel .mdc-list-item--disabled:hover{background:transparent!important}.mat-select-panel-animations-enabled mat-option:first-of-type mat-pseudo-checkbox{display:none!important}mat-option .mdc-list-item__primary-text{line-height:1.5!important;white-space:normal!important;display:flex!important;align-items:center!important}mat-option .priority-option{display:flex;align-items:center;gap:8px;width:100%}mat-option .priority-icon{width:16px;height:16px;font-size:16px;line-height:16px;flex-shrink:0}mat-option .priority-label{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: i2$3.MatSelectTrigger, selector: "mat-select-trigger" }, { kind: "component", type: i2$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatOptionModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9378
9383
|
}
|
|
9379
9384
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: PriorityComponent, decorators: [{
|
|
9380
9385
|
type: Component,
|
|
@@ -9693,7 +9698,7 @@ class AttachmentComponent {
|
|
|
9693
9698
|
return file;
|
|
9694
9699
|
}
|
|
9695
9700
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AttachmentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
9696
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: AttachmentComponent, isStandalone: true, selector: "eru-attachment", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange", fileAdded: "fileAdded", fileDeleted: "fileDeleted", fileViewed: "fileViewed" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"attachment-overlay-container\">\n <div \n class=\"attachment-cell-wrapper\"\n cdkOverlayOrigin \n #attachmentTrigger=\"cdkOverlayOrigin\"\n [class.attachment-display-editable]=\"isEditable() && !isActive()\"\n [class.attachment-display-viewable]=\"!isEditable() && hasFiles()\"\n (dblclick)=\"onActivate()\">\n @if(hasFiles()) {\n <div class=\"cell-attachment-container\">\n @if (isDrillable() && !isActive()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19 12.5C19 14.985 15.866 17 12 17C8.134 17 5 14.985 5 12.5C5 10.015 8.134 8 12 8C15.866 8 19 10.015 19 12.5Z\"\n stroke=\"#7C818C\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M13.75 12.5001C13.7716 13.1394 13.4429 13.7397 12.8925 14.0657C12.3422 14.3918 11.6578 14.3918 11.1075 14.0657C10.5571 13.7397 10.2284 13.1394 10.25 12.5001C10.2284 11.8608 10.5571 11.2606 11.1075 10.9345C11.6578 10.6084 12.3422 10.6084 12.8925 10.9345C13.4429 11.2606 13.7716 11.8608 13.75 12.5001V12.5001Z\"\n stroke=\"#7C818C\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n } @else {\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19 12.5C19 14.985 15.866 17 12 17C8.134 17 5 14.985 5 12.5C5 10.015 8.134 8 12 8C15.866 8 19 10.015 19 12.5Z\"\n stroke=\"#7C818C\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M13.75 12.5001C13.7716 13.1394 13.4429 13.7397 12.8925 14.0657C12.3422 14.3918 11.6578 14.3918 11.1075 14.0657C10.5571 13.7397 10.2284 13.1394 10.25 12.5001C10.2284 11.8608 10.5571 11.2606 11.1075 10.9345C11.6578 10.6084 12.3422 10.6084 12.8925 10.9345C13.4429 11.2606 13.7716 11.8608 13.75 12.5001V12.5001Z\"\n stroke=\"#7C818C\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n }\n </div>\n } @else {\n <div class=\"cell-attachment-container\">\n @if (isDrillable() && !isActive()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.67 11.053L10.68 15.315C10.3416 15.6932 9.85986 15.9119 9.35236 15.9178C8.84487 15.9237 8.35821 15.7162 8.01104 15.346C7.24412 14.5454 7.257 13.2788 8.04004 12.494L13.399 6.763C13.9902 6.10491 14.8315 5.72677 15.7161 5.72163C16.6006 5.71649 17.4463 6.08482 18.045 6.736C19.3222 8.14736 19.3131 10.2995 18.024 11.7L12.342 17.771C11.5334 18.5827 10.4265 19.0261 9.28113 18.9971C8.13575 18.9682 7.05268 18.4695 6.28604 17.618C4.5337 15.6414 4.57705 12.6549 6.38604 10.73L11.753 5\"\n stroke=\"#363B44\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n } @else {\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.67 11.053L10.68 15.315C10.3416 15.6932 9.85986 15.9119 9.35236 15.9178C8.84487 15.9237 8.35821 15.7162 8.01104 15.346C7.24412 14.5454 7.257 13.2788 8.04004 12.494L13.399 6.763C13.9902 6.10491 14.8315 5.72677 15.7161 5.72163C16.6006 5.71649 17.4463 6.08482 18.045 6.736C19.3222 8.14736 19.3131 10.2995 18.024 11.7L12.342 17.771C11.5334 18.5827 10.4265 19.0261 9.28113 18.9971C8.13575 18.9682 7.05268 18.4695 6.28604 17.618C4.5337 15.6414 4.57705 12.6549 6.38604 10.73L11.753 5\"\n stroke=\"#363B44\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n }\n </div>\n }\n </div>\n\n <ng-template \n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"attachmentTrigger\"\n [cdkConnectedOverlayOpen]=\"isOverlayOpen() && (isActive() || !isEditable())\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'attachment-backdrop'\"\n (backdropClick)=\"onOverlayBackdropClick()\"\n (detach)=\"closeOverlay()\">\n <div \n class=\"attachment-menu-overlay\" \n [style.width.px]=\"columnWidth() || config().columnWidth || 300\" \n [style.min-width.px]=\"300\"\n (click)=\"onOverlayClick($event)\">\n <div class=\"attachment-container\" (click)=\"$event.stopPropagation()\">\n @if (rejectionMessage()) {\n <div class=\"attachment-rejection\" role=\"alert\">{{ rejectionMessage() }}</div>\n }\n @if (isEditable()) {\n <!-- Header Section -->\n <div class=\"attachment-header\">\n <span class=\"attachment-title\">Add or Drag files</span>\n <button\n mat-flat-button\n (click)=\"onUploadClick(); $event.stopPropagation()\"\n class=\"attachment-upload-btn\"\n [disabled]=\"config().disabled\">\n Upload\n </button>\n </div>\n\n <!-- Drop zone -->\n <div\n class=\"attachment-drop-zone\"\n (drop)=\"onFileDrop($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (paste)=\"onPaste($event)\"\n (click)=\"onUploadClick(); $event.stopPropagation()\"\n [class.dragging]=\"isDragging()\">\n <div class=\"attachment-drop-content\">\n <div class=\"attachment-drop-icon\">+</div>\n <div class=\"attachment-drop-text\">\n <div class=\"primary-text\">Click to upload or drag files here</div>\n <div class=\"secondary-text\">Support multiple files</div>\n </div>\n </div>\n </div>\n\n <!-- Hidden file input -->\n <input\n #fileInput\n type=\"file\"\n multiple\n (change)=\"onFileInputChange($event)\"\n style=\"display: none;\">\n } @else {\n <!-- Read-only header -->\n <div class=\"attachment-header\">\n <span class=\"attachment-title\">Attachments</span>\n </div>\n }\n\n <!-- File list -->\n @if (hasFiles()) {\n <div class=\"attachment-file-list\">\n @for (file of currentValue(); track $index) {\n <div class=\"attachment-file-item\">\n <div class=\"file-info\">\n <mat-icon class=\"file-status-icon done-icon\">check_circle</mat-icon>\n <span class=\"file-name\">{{ getFileName(file) }}</span>\n </div>\n <div class=\"file-actions\">\n <button\n mat-icon-button\n class=\"file-action-btn\"\n (click)=\"viewFile(file, $event)\"\n title=\"View\"\n type=\"button\">\n <mat-icon>visibility</mat-icon>\n </button>\n @if (isEditable()) {\n <button\n mat-icon-button\n class=\"file-action-btn\"\n (click)=\"deleteFile(file, $event)\"\n title=\"Delete\"\n type=\"button\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </ng-template>\n</div>\n\n", styles: [".attachment-rejection{padding:8px 10px;margin-bottom:8px;border-radius:6px;background:#fef2f2;color:#b91c1c;font-size:12px;line-height:1.4}.attachment-overlay-container{width:100%;height:100%}.attachment-cell-wrapper{display:flex;align-items:center;justify-content:center;padding:4px;min-height:32px;cursor:default}.attachment-cell-wrapper.attachment-display-editable{cursor:pointer}.attachment-cell-wrapper.attachment-display-editable:hover{background-color:#0000000a}.attachment-cell-wrapper.attachment-display-viewable{cursor:pointer}.attachment-cell-wrapper.attachment-display-viewable:hover{background-color:#0000000a}.cell-attachment-container{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.drillable-value{display:flex;align-items:center;justify-content:center;cursor:pointer}.drillable-value svg{text-decoration:none}.drillable-value:hover{opacity:.8}.attachment-backdrop{background:transparent}.attachment-menu-overlay{background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;overflow:hidden;position:relative;z-index:1000}.attachment-container{padding:16px}.attachment-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.attachment-title{font-size:var(--grid-font-size-body, 12px);font-weight:500;color:var(--grid-on-surface, #1c1b1f)}.attachment-upload-btn{font-size:var(--grid-font-size-body, 12px)!important;min-width:50px}.attachment-drop-zone{border:2px dashed var(--grid-outline-variant, #cac4d0);border-radius:8px;padding:40px 20px;text-align:center;cursor:pointer;transition:all .3s ease;background:var(--grid-surface-variant, #e7e0ec);margin:16px 0}.attachment-drop-zone:hover{border-color:var(--grid-primary, #6750a4);background:var(--grid-surface-container, #f3edf7)}.attachment-drop-zone.dragging{border-color:var(--grid-primary, #6750a4);background:var(--grid-surface-container, #f3edf7);transform:scale(1.01)}.attachment-drop-content{display:flex;flex-direction:column;align-items:center;gap:12px}.attachment-drop-icon{font-size:48px;color:var(--grid-primary, #6750a4);font-weight:300;line-height:1}.attachment-drop-text .primary-text{font-family:var(--grid-font-family, \"Poppins\");font-size:14px;color:var(--grid-on-surface-variant, #49454f);font-weight:400;margin:0}.attachment-drop-text .secondary-text{font-family:var(--grid-font-family, \"Poppins\");font-size:12px;color:var(--grid-on-surface-variant, #49454f);margin-top:4px;display:block}.attachment-file-list{display:block;margin-top:16px;max-height:300px;overflow-y:auto}.attachment-file-item{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-radius:4px;margin-bottom:8px;background:var(--grid-surface-variant, #e7e0ec);transition:background-color .2s}.attachment-file-item:hover{background:var(--grid-surface-container, #f3edf7)}.file-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.file-status-icon{font-size:18px!important;width:18px!important;height:18px!important;flex-shrink:0}.file-status-icon.done-icon{color:#22c55e}.file-name{font-size:var(--grid-font-size-body, 12px);color:var(--grid-on-surface, #1c1b1f);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-actions{display:flex;gap:8px;flex-shrink:0}.file-action-btn{width:28px!important;height:28px!important;padding:0!important;display:flex!important;align-items:center;justify-content:center}.file-action-btn .mat-icon{font-size:18px;width:18px;height:18px;color:var(--grid-on-surface-variant, #49454f)}.file-action-btn:hover .mat-icon{color:var(--grid-on-surface, #1c1b1f)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.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: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$3.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$3.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9701
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: AttachmentComponent, isStandalone: true, selector: "eru-attachment", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, isEditable: { classPropertyName: "isEditable", publicName: "isEditable", isSignal: true, isRequired: false, transformFunction: null }, isActive: { classPropertyName: "isActive", publicName: "isActive", isSignal: true, isRequired: false, transformFunction: null }, isDrillable: { classPropertyName: "isDrillable", publicName: "isDrillable", isSignal: true, isRequired: false, transformFunction: null }, columnWidth: { classPropertyName: "columnWidth", publicName: "columnWidth", isSignal: true, isRequired: false, transformFunction: null }, eruGridStore: { classPropertyName: "eruGridStore", publicName: "eruGridStore", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", blur: "blur", focus: "focus", drilldownClick: "drilldownClick", editModeChange: "editModeChange", fileAdded: "fileAdded", fileDeleted: "fileDeleted", fileViewed: "fileViewed" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"attachment-overlay-container\">\n <div \n class=\"attachment-cell-wrapper\"\n cdkOverlayOrigin \n #attachmentTrigger=\"cdkOverlayOrigin\"\n [class.attachment-display-editable]=\"isEditable() && !isActive()\"\n [class.attachment-display-viewable]=\"!isEditable() && hasFiles()\"\n (dblclick)=\"onActivate()\">\n @if(hasFiles()) {\n <div class=\"cell-attachment-container\">\n @if (isDrillable() && !isActive()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19 12.5C19 14.985 15.866 17 12 17C8.134 17 5 14.985 5 12.5C5 10.015 8.134 8 12 8C15.866 8 19 10.015 19 12.5Z\"\n stroke=\"#7C818C\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M13.75 12.5001C13.7716 13.1394 13.4429 13.7397 12.8925 14.0657C12.3422 14.3918 11.6578 14.3918 11.1075 14.0657C10.5571 13.7397 10.2284 13.1394 10.25 12.5001C10.2284 11.8608 10.5571 11.2606 11.1075 10.9345C11.6578 10.6084 12.3422 10.6084 12.8925 10.9345C13.4429 11.2606 13.7716 11.8608 13.75 12.5001V12.5001Z\"\n stroke=\"#7C818C\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n } @else {\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M19 12.5C19 14.985 15.866 17 12 17C8.134 17 5 14.985 5 12.5C5 10.015 8.134 8 12 8C15.866 8 19 10.015 19 12.5Z\"\n stroke=\"#7C818C\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M13.75 12.5001C13.7716 13.1394 13.4429 13.7397 12.8925 14.0657C12.3422 14.3918 11.6578 14.3918 11.1075 14.0657C10.5571 13.7397 10.2284 13.1394 10.25 12.5001C10.2284 11.8608 10.5571 11.2606 11.1075 10.9345C11.6578 10.6084 12.3422 10.6084 12.8925 10.9345C13.4429 11.2606 13.7716 11.8608 13.75 12.5001V12.5001Z\"\n stroke=\"#7C818C\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n }\n </div>\n } @else {\n <div class=\"cell-attachment-container\">\n @if (isDrillable() && !isActive()) {\n <span class=\"drillable-value\" (click)=\"onDrillableClick($event)\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.67 11.053L10.68 15.315C10.3416 15.6932 9.85986 15.9119 9.35236 15.9178C8.84487 15.9237 8.35821 15.7162 8.01104 15.346C7.24412 14.5454 7.257 13.2788 8.04004 12.494L13.399 6.763C13.9902 6.10491 14.8315 5.72677 15.7161 5.72163C16.6006 5.71649 17.4463 6.08482 18.045 6.736C19.3222 8.14736 19.3131 10.2995 18.024 11.7L12.342 17.771C11.5334 18.5827 10.4265 19.0261 9.28113 18.9971C8.13575 18.9682 7.05268 18.4695 6.28604 17.618C4.5337 15.6414 4.57705 12.6549 6.38604 10.73L11.753 5\"\n stroke=\"#363B44\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n } @else {\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.67 11.053L10.68 15.315C10.3416 15.6932 9.85986 15.9119 9.35236 15.9178C8.84487 15.9237 8.35821 15.7162 8.01104 15.346C7.24412 14.5454 7.257 13.2788 8.04004 12.494L13.399 6.763C13.9902 6.10491 14.8315 5.72677 15.7161 5.72163C16.6006 5.71649 17.4463 6.08482 18.045 6.736C19.3222 8.14736 19.3131 10.2995 18.024 11.7L12.342 17.771C11.5334 18.5827 10.4265 19.0261 9.28113 18.9971C8.13575 18.9682 7.05268 18.4695 6.28604 17.618C4.5337 15.6414 4.57705 12.6549 6.38604 10.73L11.753 5\"\n stroke=\"#363B44\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n }\n </div>\n }\n </div>\n\n <ng-template \n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"attachmentTrigger\"\n [cdkConnectedOverlayOpen]=\"isOverlayOpen() && (isActive() || !isEditable())\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'attachment-backdrop'\"\n (backdropClick)=\"onOverlayBackdropClick()\"\n (detach)=\"closeOverlay()\">\n <div \n class=\"attachment-menu-overlay\" \n [style.width.px]=\"columnWidth() || config().columnWidth || 300\" \n [style.min-width.px]=\"300\"\n (click)=\"onOverlayClick($event)\">\n <div class=\"attachment-container\" (click)=\"$event.stopPropagation()\">\n @if (rejectionMessage()) {\n <div class=\"attachment-rejection\" role=\"alert\">{{ rejectionMessage() }}</div>\n }\n @if (isEditable()) {\n <!-- Header Section -->\n <div class=\"attachment-header\">\n <span class=\"attachment-title\">Add or Drag files</span>\n <button\n mat-flat-button\n (click)=\"onUploadClick(); $event.stopPropagation()\"\n class=\"attachment-upload-btn\"\n [disabled]=\"config().disabled\">\n Upload\n </button>\n </div>\n\n <!-- Drop zone -->\n <div\n class=\"attachment-drop-zone\"\n (drop)=\"onFileDrop($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (paste)=\"onPaste($event)\"\n (click)=\"onUploadClick(); $event.stopPropagation()\"\n [class.dragging]=\"isDragging()\">\n <div class=\"attachment-drop-content\">\n <div class=\"attachment-drop-icon\">+</div>\n <div class=\"attachment-drop-text\">\n <div class=\"primary-text\">Click to upload or drag files here</div>\n <div class=\"secondary-text\">Support multiple files</div>\n </div>\n </div>\n </div>\n\n <!-- Hidden file input -->\n <input\n #fileInput\n type=\"file\"\n multiple\n (change)=\"onFileInputChange($event)\"\n style=\"display: none;\">\n } @else {\n <!-- Read-only header -->\n <div class=\"attachment-header\">\n <span class=\"attachment-title\">Attachments</span>\n </div>\n }\n\n <!-- File list -->\n @if (hasFiles()) {\n <div class=\"attachment-file-list\">\n @for (file of currentValue(); track $index) {\n <div class=\"attachment-file-item\">\n <div class=\"file-info\">\n <mat-icon class=\"file-status-icon done-icon\">check_circle</mat-icon>\n <span class=\"file-name\">{{ getFileName(file) }}</span>\n </div>\n <div class=\"file-actions\">\n <button\n mat-icon-button\n class=\"file-action-btn\"\n (click)=\"viewFile(file, $event)\"\n title=\"View\"\n type=\"button\">\n <mat-icon>visibility</mat-icon>\n </button>\n @if (isEditable()) {\n <button\n mat-icon-button\n class=\"file-action-btn\"\n (click)=\"deleteFile(file, $event)\"\n title=\"Delete\"\n type=\"button\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n }\n </div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </ng-template>\n</div>\n\n", styles: [".attachment-rejection{padding:8px 10px;margin-bottom:8px;border-radius:6px;background:#fef2f2;color:#b91c1c;font-size:12px;line-height:1.4}.attachment-overlay-container{width:100%;height:100%}.attachment-cell-wrapper{display:flex;align-items:center;justify-content:center;padding:4px;min-height:32px;cursor:default}.attachment-cell-wrapper.attachment-display-editable{cursor:pointer}.attachment-cell-wrapper.attachment-display-editable:hover{background-color:#0000000a}.attachment-cell-wrapper.attachment-display-viewable{cursor:pointer}.attachment-cell-wrapper.attachment-display-viewable:hover{background-color:#0000000a}.cell-attachment-container{display:flex;align-items:center;justify-content:center;width:100%;height:100%}.drillable-value{display:flex;align-items:center;justify-content:center;cursor:pointer}.drillable-value svg{text-decoration:none}.drillable-value:hover{opacity:.8}.attachment-backdrop{background:transparent}.attachment-menu-overlay{background:#fff;border-radius:8px;box-shadow:0 4px 12px #00000026;overflow:hidden;position:relative;z-index:1000}.attachment-container{padding:16px}.attachment-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.attachment-title{font-size:var(--grid-font-size-body, 12px);font-weight:500;color:var(--grid-on-surface, #1c1b1f)}.attachment-upload-btn{font-size:var(--grid-font-size-body, 12px)!important;min-width:50px}.attachment-drop-zone{border:2px dashed var(--grid-outline-variant, #cac4d0);border-radius:8px;padding:40px 20px;text-align:center;cursor:pointer;transition:all .3s ease;background:var(--grid-surface-variant, #e7e0ec);margin:16px 0}.attachment-drop-zone:hover{border-color:var(--grid-primary, #6750a4);background:var(--grid-surface-container, #f3edf7)}.attachment-drop-zone.dragging{border-color:var(--grid-primary, #6750a4);background:var(--grid-surface-container, #f3edf7);transform:scale(1.01)}.attachment-drop-content{display:flex;flex-direction:column;align-items:center;gap:12px}.attachment-drop-icon{font-size:48px;color:var(--grid-primary, #6750a4);font-weight:300;line-height:1}.attachment-drop-text .primary-text{font-family:var(--grid-font-family, \"Poppins\");font-size:14px;color:var(--grid-on-surface-variant, #49454f);font-weight:400;margin:0}.attachment-drop-text .secondary-text{font-family:var(--grid-font-family, \"Poppins\");font-size:12px;color:var(--grid-on-surface-variant, #49454f);margin-top:4px;display:block}.attachment-file-list{display:block;margin-top:16px;max-height:300px;overflow-y:auto}.attachment-file-item{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-radius:4px;margin-bottom:8px;background:var(--grid-surface-variant, #e7e0ec);transition:background-color .2s}.attachment-file-item:hover{background:var(--grid-surface-container, #f3edf7)}.file-info{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.file-status-icon{font-size:18px!important;width:18px!important;height:18px!important;flex-shrink:0}.file-status-icon.done-icon{color:#22c55e}.file-name{font-size:var(--grid-font-size-body, 12px);color:var(--grid-on-surface, #1c1b1f);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file-actions{display:flex;gap:8px;flex-shrink:0}.file-action-btn{width:28px!important;height:28px!important;padding:0!important;display:flex!important;align-items:center;justify-content:center}.file-action-btn .mat-icon{font-size:18px;width:18px;height:18px;color:var(--grid-on-surface-variant, #49454f)}.file-action-btn:hover .mat-icon{color:var(--grid-on-surface, #1c1b1f)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.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: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1$3.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1$3.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
9697
9702
|
}
|
|
9698
9703
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AttachmentComponent, decorators: [{
|
|
9699
9704
|
type: Component,
|
|
@@ -11818,6 +11823,12 @@ const OPTION_FIELDS = [
|
|
|
11818
11823
|
const STATIC_COLOR_OPTION_FIELDS = [
|
|
11819
11824
|
{ key: 'options', label: 'Options', control: 'color_list', defaultColor: '#9CA3AF' },
|
|
11820
11825
|
];
|
|
11826
|
+
// tag is the only static-colour type whose dropdown carries a filter box, so it
|
|
11827
|
+
// gets the same searchable toggle select and people expose.
|
|
11828
|
+
const TAG_FIELDS = [
|
|
11829
|
+
{ key: 'searchable', label: 'Searchable', control: 'checkbox', defaultValue: true },
|
|
11830
|
+
...STATIC_COLOR_OPTION_FIELDS,
|
|
11831
|
+
];
|
|
11821
11832
|
const DATE_FIELDS = [
|
|
11822
11833
|
// Shared list, so the panel offers exactly what eru-studio and processo do.
|
|
11823
11834
|
{ key: 'date_format', label: 'Date format', control: 'select', options: DATE_FORMATS },
|
|
@@ -11844,7 +11855,7 @@ const DATATYPE_FIELDS = {
|
|
|
11844
11855
|
website: WEBSITE_FIELDS,
|
|
11845
11856
|
dropdown_single_select: OPTION_FIELDS,
|
|
11846
11857
|
dropdown_multi_select: OPTION_FIELDS,
|
|
11847
|
-
tag:
|
|
11858
|
+
tag: TAG_FIELDS,
|
|
11848
11859
|
priority: STATIC_COLOR_OPTION_FIELDS,
|
|
11849
11860
|
status: [
|
|
11850
11861
|
{ key: 'open_status', label: 'Open statuses', control: 'color_list', defaultColor: '#22C55E' },
|
|
@@ -12159,7 +12170,7 @@ class ColumnDesignPanelComponent {
|
|
|
12159
12170
|
this.gridStore.selectDesignColumn(null);
|
|
12160
12171
|
}
|
|
12161
12172
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ColumnDesignPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
12162
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ColumnDesignPanelComponent, isStandalone: true, selector: "eru-column-design-panel", ngImport: i0, template: "@if (isOpen()) {\n<div class=\"design-panel-backdrop\" (click)=\"close()\"></div>\n}\n<aside class=\"column-design-panel\" [class.open]=\"isOpen()\">\n @if (field(); as col) {\n <header class=\"design-panel-header\">\n <div class=\"design-panel-title\">\n <mat-icon>tune</mat-icon>\n <span>{{ col.label || col.name }}</span>\n </div>\n <button mat-icon-button (click)=\"close()\" title=\"Close\">\n <mat-icon>close</mat-icon>\n </button>\n </header>\n\n <div class=\"design-panel-body\">\n <!-- Which field is being designed. A pivot with one measure renders no\n measure-name row, so its single header cell stands for the column\n dimension and the measure at once and can only open one of them; this\n reaches the other. Also the way to a header too narrow to click, or a\n hidden column. Only shown when there is more than one thing to pick. -->\n @if (designTargets().length > 0 && targetCount() > 1) {\n <div class=\"design-field design-target\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Editing</mat-label>\n <mat-select [ngModel]=\"gridStore.selectedDesignColumn()\"\n (ngModelChange)=\"gridStore.selectDesignColumn($event)\">\n @for (group of designTargets(); track group.group) {\n <mat-optgroup [label]=\"group.group\">\n @for (target of group.fields; track target.name) {\n <mat-option [value]=\"target.name\">{{ target.label || target.name }}</mat-option>\n }\n </mat-optgroup>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n\n <!-- Where this column's metadata comes from: typed in here, or inherited\n from a field in the host app's data model so it stays defined once. -->\n <div class=\"design-field design-meta-source\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Metadata source</mat-label>\n <mat-select [ngModel]=\"metaSource()\" (ngModelChange)=\"onMetaSourceChange($event)\">\n <mat-option value=\"manual\">Defined here</mat-option>\n <mat-option value=\"entity\">Mapped to data model field</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (metaSource() === 'entity') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Entity</mat-label>\n <mat-select [ngModel]=\"getValue('mapped_entity')\" (ngModelChange)=\"onEntityChange($event)\"\n (openedChange)=\"$event && requestEntities()\">\n @for (opt of entityOptions(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n @if (getValue('mapped_entity')) {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Field</mat-label>\n <mat-select [ngModel]=\"getValue('mapped_field')\" (ngModelChange)=\"onEntityFieldChange($event)\">\n @for (opt of entityFieldOptions(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n\n @if (isEntityMapped()) {\n <p class=\"design-meta-hint\">\n Colours, options and formatting come from the data model. Edit them there to update\n every grid that maps this field.\n </p>\n }\n }\n </div>\n\n @for (def of metaFields(); track def.key) {\n <div class=\"design-field\" [class.design-field-inherited]=\"isInherited(def.key)\"\n [title]=\"isInherited(def.key) ? 'Inherited from the mapped data model field' : ''\">\n @switch (def.control) {\n\n @case ('text') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>{{ def.label }}</mat-label>\n <input matInput [ngModel]=\"getValue(def.key)\" (ngModelChange)=\"onText(def.key, $event)\" />\n </mat-form-field>\n }\n\n @case ('number') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>{{ def.label }}</mat-label>\n <input matInput type=\"number\" [ngModel]=\"getValue(def.key)\" (ngModelChange)=\"onNumber(def.key, $event)\" />\n </mat-form-field>\n }\n\n @case ('select') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>{{ def.label }}</mat-label>\n <mat-select [ngModel]=\"getValue(def.key)\" (ngModelChange)=\"onSelect(def.key, $event)\">\n @for (opt of def.options; track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n\n @case ('checkbox') {\n <mat-checkbox [checked]=\"isChecked(def)\" (change)=\"onCheckbox(def.key, $event.checked)\">\n {{ def.label }}\n </mat-checkbox>\n }\n\n @case ('day_chips') {\n <div class=\"day-chips\">\n <label class=\"day-chips-label\">{{ def.label }}</label>\n <div class=\"day-chips-row\">\n @for (day of weekDays; track day) {\n <button type=\"button\" class=\"day-chip\" [class.selected]=\"isDaySelected(def.key, day)\"\n (click)=\"toggleDay(def.key, day)\">{{ day }}</button>\n }\n </div>\n </div>\n }\n\n @case ('list') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>{{ def.label }}</mat-label>\n <textarea matInput rows=\"4\" [ngModel]=\"listText(def.key)\"\n (ngModelChange)=\"onList(def.key, $event)\"></textarea>\n </mat-form-field>\n }\n\n @case ('color_list') {\n <div class=\"color-list\">\n <label class=\"color-list-label\">{{ def.label }}</label>\n <div class=\"color-list-chips\">\n @for (opt of colorListItems(def.key); track $index) {\n <div class=\"color-list-chip\">\n <input type=\"color\" class=\"color-list-dot\" [value]=\"opt.color || '#9CA3AF'\"\n (input)=\"onColorListColorChange(def.key, $index, $any($event.target).value)\" title=\"Change colour\" />\n <span class=\"color-list-name\">{{ opt.name }}</span>\n <button type=\"button\" class=\"color-list-remove\" (click)=\"removeColorListItem(def.key, $index)\"\n title=\"Remove\">×</button>\n </div>\n }\n </div>\n <input class=\"color-list-add\" type=\"text\" placeholder=\"Add option, press Enter\"\n (keydown.enter)=\"addColorListItem(def.key, $any($event.target).value, def.defaultColor || '#9CA3AF'); $any($event.target).value = ''\" />\n </div>\n }\n\n @case ('range_color_list') {\n <div class=\"range-list\">\n <label class=\"range-list-label\">{{ def.label }}</label>\n @for (r of rangeListItems(def.key); track $index) {\n <div class=\"range-list-row\">\n <input type=\"number\" class=\"range-list-num\" min=\"0\" max=\"100\" [value]=\"r.from\"\n (input)=\"onRangeChange(def.key, $index, 'from', $any($event.target).value)\" title=\"From\" />\n <span class=\"range-list-sep\">\u2013</span>\n <input type=\"number\" class=\"range-list-num\" min=\"0\" max=\"100\" [value]=\"r.to\"\n (input)=\"onRangeChange(def.key, $index, 'to', $any($event.target).value)\" title=\"To\" />\n <input type=\"color\" class=\"range-list-color\" [value]=\"r.color || '#22C55E'\"\n (input)=\"onRangeColorChange(def.key, $index, $any($event.target).value)\" title=\"Colour\" />\n <button type=\"button\" class=\"range-list-remove\" (click)=\"removeRangeItem(def.key, $index)\"\n title=\"Remove\">×</button>\n </div>\n }\n <button type=\"button\" class=\"range-list-add\" (click)=\"addRangeItem(def.key)\">+ Add range</button>\n </div>\n }\n\n }\n </div>\n }\n </div>\n }\n</aside>\n", styles: [".design-panel-backdrop{position:fixed;inset:0;background:#0000002e;z-index:1000}.column-design-panel{position:fixed;top:0;right:0;bottom:0;width:360px;max-width:90vw;background:var(--grid-surface, #fff);box-shadow:-4px 0 16px #00000029;transform:translate(100%);transition:transform .22s ease;z-index:1001;display:flex;flex-direction:column;font-family:var(--grid-font-family, inherit)}.column-design-panel.open{transform:translate(0)}.design-panel-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--grid-border-color, #e0e0e0)}.design-panel-header .design-panel-title{display:flex;align-items:center;gap:8px;font-weight:600;font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.design-panel-body{padding:16px;overflow-y:auto;flex:1}.design-panel-body .design-field{margin-bottom:4px}.design-panel-body .design-field .full-width{width:100%}.design-panel-body .design-field mat-checkbox{display:block;margin:8px 0 16px}.design-panel-body .color-list{margin:4px 0 16px}.design-panel-body .color-list .color-list-label{display:block;font-size:12px;color:var(--grid-on-surface-variant, #49454f);margin-bottom:6px}.design-panel-body .color-list .color-list-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.design-panel-body .color-list .color-list-chip{display:inline-flex;align-items:center;gap:6px;padding:3px 8px 3px 4px;border:1px solid var(--grid-outline-variant, #cac4d0);border-radius:16px;background:var(--grid-surface, #fff);font-size:12px}.design-panel-body .color-list .color-list-dot{width:18px;height:18px;padding:0;border:none;background:none;border-radius:50%;cursor:pointer}.design-panel-body .color-list .color-list-remove{border:none;background:none;cursor:pointer;font-size:14px;line-height:1;color:var(--grid-on-surface-variant, #49454f)}.design-panel-body .color-list .color-list-remove:hover{color:var(--grid-error, #b3261e)}.design-panel-body .color-list .color-list-add{width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid var(--grid-outline-variant, #cac4d0);border-radius:6px;font-size:13px;outline:none}.design-panel-body .color-list .color-list-add:focus{border-color:var(--grid-primary, #6750a4)}.range-list{margin:4px 0 16px}.range-list .range-list-label{display:block;font-size:12px;color:var(--grid-on-surface-variant, #49454f);margin-bottom:6px}.range-list .range-list-row{display:flex;align-items:center;gap:6px;margin-bottom:6px}.range-list .range-list-num{width:56px;padding:6px 8px;border:1px solid var(--grid-outline-variant, #cac4d0);border-radius:6px;font-size:13px;outline:none}.range-list .range-list-num:focus{border-color:var(--grid-primary, #6750a4)}.range-list .range-list-sep{color:var(--grid-on-surface-variant, #49454f)}.range-list .range-list-color{width:28px;height:28px;padding:0;border:1px solid var(--grid-outline-variant, #cac4d0);border-radius:6px;background:none;cursor:pointer}.range-list .range-list-remove{margin-left:auto;border:none;background:none;cursor:pointer;font-size:18px;line-height:1;color:var(--grid-on-surface-variant, #49454f)}.range-list .range-list-remove:hover{color:var(--grid-error, #b3261e)}.range-list .range-list-add{margin-top:2px;padding:6px 10px;border:1px dashed var(--grid-outline-variant, #cac4d0);border-radius:6px;background:none;font-size:13px;cursor:pointer;color:var(--grid-primary, #6750a4)}.range-list .range-list-add:hover{background:var(--grid-surface-variant, #f3edf7)}.day-chips{display:flex;flex-direction:column;gap:6px}.day-chips-label{font-size:12px;color:var(--eru-on-surface-variant, #5f6368)}.day-chips-row{display:flex;flex-wrap:wrap;gap:6px}.day-chip{border:1px solid var(--eru-outline, #c4c7c5);background:transparent;border-radius:16px;padding:4px 12px;font-size:12px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s,color .15s,border-color .15s}.day-chip.selected{background:var(--eru-primary, #1a73e8);border-color:var(--eru-primary, #1a73e8);color:#fff}.design-field-inherited{opacity:.55;pointer-events:none}.design-meta-source{padding-bottom:8px;border-bottom:1px solid var(--grid-outline-variant, #e0e0e0);margin-bottom:12px}.design-meta-hint{margin:4px 0 0;font-size:11px;line-height:1.4;color:var(--grid-on-surface-variant, #49454f)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { 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: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i2$2.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i4$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
12173
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: ColumnDesignPanelComponent, isStandalone: true, selector: "eru-column-design-panel", ngImport: i0, template: "@if (isOpen()) {\n<div class=\"design-panel-backdrop\" (click)=\"close()\"></div>\n}\n<aside class=\"column-design-panel\" [class.open]=\"isOpen()\">\n @if (field(); as col) {\n <header class=\"design-panel-header\">\n <div class=\"design-panel-title\">\n <mat-icon>tune</mat-icon>\n <span>{{ col.label || col.name }}</span>\n </div>\n <button mat-icon-button (click)=\"close()\" title=\"Close\">\n <mat-icon>close</mat-icon>\n </button>\n </header>\n\n <div class=\"design-panel-body\">\n <!-- Which field is being designed. A pivot with one measure renders no\n measure-name row, so its single header cell stands for the column\n dimension and the measure at once and can only open one of them; this\n reaches the other. Also the way to a header too narrow to click, or a\n hidden column. Only shown when there is more than one thing to pick. -->\n @if (designTargets().length > 0 && targetCount() > 1) {\n <div class=\"design-field design-target\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Editing</mat-label>\n <mat-select [ngModel]=\"gridStore.selectedDesignColumn()\"\n (ngModelChange)=\"gridStore.selectDesignColumn($event)\">\n @for (group of designTargets(); track group.group) {\n <mat-optgroup [label]=\"group.group\">\n @for (target of group.fields; track target.name) {\n <mat-option [value]=\"target.name\">{{ target.label || target.name }}</mat-option>\n }\n </mat-optgroup>\n }\n </mat-select>\n </mat-form-field>\n </div>\n }\n\n <!-- Where this column's metadata comes from: typed in here, or inherited\n from a field in the host app's data model so it stays defined once. -->\n <div class=\"design-field design-meta-source\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Metadata source</mat-label>\n <mat-select [ngModel]=\"metaSource()\" (ngModelChange)=\"onMetaSourceChange($event)\">\n <mat-option value=\"manual\">Defined here</mat-option>\n <mat-option value=\"entity\">Mapped to data model field</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (metaSource() === 'entity') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Entity</mat-label>\n <mat-select [ngModel]=\"getValue('mapped_entity')\" (ngModelChange)=\"onEntityChange($event)\"\n (openedChange)=\"$event && requestEntities()\">\n @for (opt of entityOptions(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n @if (getValue('mapped_entity')) {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Field</mat-label>\n <mat-select [ngModel]=\"getValue('mapped_field')\" (ngModelChange)=\"onEntityFieldChange($event)\">\n @for (opt of entityFieldOptions(); track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n\n @if (isEntityMapped()) {\n <p class=\"design-meta-hint\">\n Colours, options and formatting come from the data model. Edit them there to update\n every grid that maps this field.\n </p>\n }\n }\n </div>\n\n @for (def of metaFields(); track def.key) {\n <div class=\"design-field\" [class.design-field-inherited]=\"isInherited(def.key)\"\n [title]=\"isInherited(def.key) ? 'Inherited from the mapped data model field' : ''\">\n @switch (def.control) {\n\n @case ('text') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>{{ def.label }}</mat-label>\n <input matInput [ngModel]=\"getValue(def.key)\" (ngModelChange)=\"onText(def.key, $event)\" />\n </mat-form-field>\n }\n\n @case ('number') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>{{ def.label }}</mat-label>\n <input matInput type=\"number\" [ngModel]=\"getValue(def.key)\" (ngModelChange)=\"onNumber(def.key, $event)\" />\n </mat-form-field>\n }\n\n @case ('select') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>{{ def.label }}</mat-label>\n <mat-select [ngModel]=\"getValue(def.key)\" (ngModelChange)=\"onSelect(def.key, $event)\">\n @for (opt of def.options; track opt.value) {\n <mat-option [value]=\"opt.value\">{{ opt.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n }\n\n @case ('checkbox') {\n <mat-checkbox [checked]=\"isChecked(def)\" (change)=\"onCheckbox(def.key, $event.checked)\">\n {{ def.label }}\n </mat-checkbox>\n }\n\n @case ('day_chips') {\n <div class=\"day-chips\">\n <label class=\"day-chips-label\">{{ def.label }}</label>\n <div class=\"day-chips-row\">\n @for (day of weekDays; track day) {\n <button type=\"button\" class=\"day-chip\" [class.selected]=\"isDaySelected(def.key, day)\"\n (click)=\"toggleDay(def.key, day)\">{{ day }}</button>\n }\n </div>\n </div>\n }\n\n @case ('list') {\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>{{ def.label }}</mat-label>\n <textarea matInput rows=\"4\" [ngModel]=\"listText(def.key)\"\n (ngModelChange)=\"onList(def.key, $event)\"></textarea>\n </mat-form-field>\n }\n\n @case ('color_list') {\n <div class=\"color-list\">\n <label class=\"color-list-label\">{{ def.label }}</label>\n <div class=\"color-list-chips\">\n @for (opt of colorListItems(def.key); track $index) {\n <div class=\"color-list-chip\">\n <input type=\"color\" class=\"color-list-dot\" [value]=\"opt.color || '#9CA3AF'\"\n (input)=\"onColorListColorChange(def.key, $index, $any($event.target).value)\" title=\"Change colour\" />\n <span class=\"color-list-name\">{{ opt.name }}</span>\n <button type=\"button\" class=\"color-list-remove\" (click)=\"removeColorListItem(def.key, $index)\"\n title=\"Remove\">×</button>\n </div>\n }\n </div>\n <input class=\"color-list-add\" type=\"text\" placeholder=\"Add option, press Enter\"\n (keydown.enter)=\"addColorListItem(def.key, $any($event.target).value, def.defaultColor || '#9CA3AF'); $any($event.target).value = ''\" />\n </div>\n }\n\n @case ('range_color_list') {\n <div class=\"range-list\">\n <label class=\"range-list-label\">{{ def.label }}</label>\n @for (r of rangeListItems(def.key); track $index) {\n <div class=\"range-list-row\">\n <input type=\"number\" class=\"range-list-num\" min=\"0\" max=\"100\" [value]=\"r.from\"\n (input)=\"onRangeChange(def.key, $index, 'from', $any($event.target).value)\" title=\"From\" />\n <span class=\"range-list-sep\">\u2013</span>\n <input type=\"number\" class=\"range-list-num\" min=\"0\" max=\"100\" [value]=\"r.to\"\n (input)=\"onRangeChange(def.key, $index, 'to', $any($event.target).value)\" title=\"To\" />\n <input type=\"color\" class=\"range-list-color\" [value]=\"r.color || '#22C55E'\"\n (input)=\"onRangeColorChange(def.key, $index, $any($event.target).value)\" title=\"Colour\" />\n <button type=\"button\" class=\"range-list-remove\" (click)=\"removeRangeItem(def.key, $index)\"\n title=\"Remove\">×</button>\n </div>\n }\n <button type=\"button\" class=\"range-list-add\" (click)=\"addRangeItem(def.key)\">+ Add range</button>\n </div>\n }\n\n }\n </div>\n }\n </div>\n }\n</aside>\n", styles: [".design-panel-backdrop{position:fixed;inset:0;background:#0000002e;z-index:1000}.column-design-panel{position:fixed;top:0;right:0;bottom:0;width:360px;max-width:90vw;background:var(--grid-surface, #fff);box-shadow:-4px 0 16px #00000029;transform:translate(100%);transition:transform .22s ease;z-index:1001;display:flex;flex-direction:column;font-family:var(--grid-font-family, inherit)}.column-design-panel.open{transform:translate(0)}.design-panel-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--grid-border-color, #e0e0e0)}.design-panel-header .design-panel-title{display:flex;align-items:center;gap:8px;font-weight:600;font-size:15px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.design-panel-body{padding:16px;overflow-y:auto;flex:1}.design-panel-body .design-field{margin-bottom:4px}.design-panel-body .design-field .full-width{width:100%}.design-panel-body .design-field mat-checkbox{display:block;margin:8px 0 16px}.design-panel-body .color-list{margin:4px 0 16px}.design-panel-body .color-list .color-list-label{display:block;font-size:12px;color:var(--grid-on-surface-variant, #49454f);margin-bottom:6px}.design-panel-body .color-list .color-list-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}.design-panel-body .color-list .color-list-chip{display:inline-flex;align-items:center;gap:6px;padding:3px 8px 3px 4px;border:1px solid var(--grid-outline-variant, #cac4d0);border-radius:16px;background:var(--grid-surface, #fff);font-size:12px}.design-panel-body .color-list .color-list-dot{width:18px;height:18px;padding:0;border:none;background:none;border-radius:50%;cursor:pointer}.design-panel-body .color-list .color-list-remove{border:none;background:none;cursor:pointer;font-size:14px;line-height:1;color:var(--grid-on-surface-variant, #49454f)}.design-panel-body .color-list .color-list-remove:hover{color:var(--grid-error, #b3261e)}.design-panel-body .color-list .color-list-add{width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid var(--grid-outline-variant, #cac4d0);border-radius:6px;font-size:13px;outline:none}.design-panel-body .color-list .color-list-add:focus{border-color:var(--grid-primary, #6750a4)}.range-list{margin:4px 0 16px}.range-list .range-list-label{display:block;font-size:12px;color:var(--grid-on-surface-variant, #49454f);margin-bottom:6px}.range-list .range-list-row{display:flex;align-items:center;gap:6px;margin-bottom:6px}.range-list .range-list-num{width:56px;padding:6px 8px;border:1px solid var(--grid-outline-variant, #cac4d0);border-radius:6px;font-size:13px;outline:none}.range-list .range-list-num:focus{border-color:var(--grid-primary, #6750a4)}.range-list .range-list-sep{color:var(--grid-on-surface-variant, #49454f)}.range-list .range-list-color{width:28px;height:28px;padding:0;border:1px solid var(--grid-outline-variant, #cac4d0);border-radius:6px;background:none;cursor:pointer}.range-list .range-list-remove{margin-left:auto;border:none;background:none;cursor:pointer;font-size:18px;line-height:1;color:var(--grid-on-surface-variant, #49454f)}.range-list .range-list-remove:hover{color:var(--grid-error, #b3261e)}.range-list .range-list-add{margin-top:2px;padding:6px 10px;border:1px dashed var(--grid-outline-variant, #cac4d0);border-radius:6px;background:none;font-size:13px;cursor:pointer;color:var(--grid-primary, #6750a4)}.range-list .range-list-add:hover{background:var(--grid-surface-variant, #f3edf7)}.day-chips{display:flex;flex-direction:column;gap:6px}.day-chips-label{font-size:12px;color:var(--eru-on-surface-variant, #5f6368)}.day-chips-row{display:flex;flex-wrap:wrap;gap:6px}.day-chip{border:1px solid var(--eru-outline, #c4c7c5);background:transparent;border-radius:16px;padding:4px 12px;font-size:12px;cursor:pointer;-webkit-user-select:none;user-select:none;transition:background .15s,color .15s,border-color .15s}.day-chip.selected{background:var(--eru-primary, #1a73e8);border-color:var(--eru-primary, #1a73e8);color:#fff}.design-field-inherited{opacity:.55;pointer-events:none}.design-meta-source{padding-bottom:8px;border-bottom:1px solid var(--grid-outline-variant, #e0e0e0);margin-bottom:12px}.design-meta-hint{margin:4px 0 0;font-size:11px;line-height:1.4;color:var(--grid-on-surface-variant, #49454f)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { 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: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i2$3.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i2$3.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i2$3.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i2$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
12163
12174
|
}
|
|
12164
12175
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ColumnDesignPanelComponent, decorators: [{
|
|
12165
12176
|
type: Component,
|
|
@@ -12354,6 +12365,8 @@ class EruGridComponent {
|
|
|
12354
12365
|
isSmViewport = signal(false, ...(ngDevMode ? [{ debugName: "isSmViewport" }] : []));
|
|
12355
12366
|
containerHeight = signal(400, ...(ngDevMode ? [{ debugName: "containerHeight" }] : [])); // Internal tracking for available height
|
|
12356
12367
|
resizeObserver = null;
|
|
12368
|
+
boardViewportObserver = null;
|
|
12369
|
+
boardViewportsSubscription = null;
|
|
12357
12370
|
groupIntersectionObserver = null;
|
|
12358
12371
|
isColumnReordering = signal(false, ...(ngDevMode ? [{ debugName: "isColumnReordering" }] : []));
|
|
12359
12372
|
firstTr = 0;
|
|
@@ -12646,6 +12659,10 @@ class EruGridComponent {
|
|
|
12646
12659
|
const config = this.gridStore.configuration();
|
|
12647
12660
|
return config?.config?.sortBar ?? false;
|
|
12648
12661
|
}, ...(ngDevMode ? [{ debugName: "showSortBar" }] : []));
|
|
12662
|
+
showBoardColumnHeader = computed(() => {
|
|
12663
|
+
const config = this.gridStore.configuration();
|
|
12664
|
+
return config?.config?.boardColumnHeader ?? true;
|
|
12665
|
+
}, ...(ngDevMode ? [{ debugName: "showBoardColumnHeader" }] : []));
|
|
12649
12666
|
// Group bar configuration
|
|
12650
12667
|
showGroupBar = computed(() => {
|
|
12651
12668
|
const config = this.gridStore.configuration();
|
|
@@ -13066,6 +13083,8 @@ class EruGridComponent {
|
|
|
13066
13083
|
setVar('--eru-board-card-hover-bg', cfg?.boardCardHoverBg);
|
|
13067
13084
|
setVar('--eru-board-card-selected-bg', cfg?.boardCardSelectedBg);
|
|
13068
13085
|
setVar('--eru-board-card-selected-outline', cfg?.boardCardSelectedOutline);
|
|
13086
|
+
setVar('--eru-board-count-color', cfg?.boardCountTextColor);
|
|
13087
|
+
setVar('--eru-board-count-bg', cfg?.boardCountBg);
|
|
13069
13088
|
// Responsive board layout: min column width (drives how many columns fit
|
|
13070
13089
|
// per row before wrapping/stacking) and per-column height (vertical scroll).
|
|
13071
13090
|
const minW = cfg?.boardColumnMinWidth;
|
|
@@ -13204,16 +13223,46 @@ class EruGridComponent {
|
|
|
13204
13223
|
});
|
|
13205
13224
|
this.resizeObserver.observe(this.elementRef.nativeElement);
|
|
13206
13225
|
}
|
|
13226
|
+
this.observeBoardViewports();
|
|
13227
|
+
this.boardViewportsSubscription = this.allViewports?.changes.subscribe(() => this.observeBoardViewports()) ?? null;
|
|
13207
13228
|
// For debugging: expose method to window
|
|
13208
13229
|
if (typeof window !== 'undefined') {
|
|
13209
13230
|
window.recalculateScrollbar = () => this.recalculateScrollbarCompensation();
|
|
13210
13231
|
}
|
|
13211
13232
|
}
|
|
13233
|
+
observeBoardViewports() {
|
|
13234
|
+
if (typeof ResizeObserver === 'undefined')
|
|
13235
|
+
return;
|
|
13236
|
+
this.boardViewportObserver?.disconnect();
|
|
13237
|
+
const elements = (this.allViewports?.toArray() ?? [])
|
|
13238
|
+
.map(viewport => viewport.elementRef.nativeElement)
|
|
13239
|
+
.filter(element => element.classList.contains('board-column-body'));
|
|
13240
|
+
if (elements.length === 0)
|
|
13241
|
+
return;
|
|
13242
|
+
if (!this.boardViewportObserver) {
|
|
13243
|
+
this.boardViewportObserver = new ResizeObserver(entries => {
|
|
13244
|
+
for (const entry of entries) {
|
|
13245
|
+
const viewport = (this.allViewports?.toArray() ?? [])
|
|
13246
|
+
.find(candidate => candidate.elementRef.nativeElement === entry.target);
|
|
13247
|
+
viewport?.checkViewportSize();
|
|
13248
|
+
}
|
|
13249
|
+
});
|
|
13250
|
+
}
|
|
13251
|
+
elements.forEach(element => this.boardViewportObserver.observe(element));
|
|
13252
|
+
}
|
|
13212
13253
|
ngOnDestroy() {
|
|
13213
13254
|
if (this.resizeObserver) {
|
|
13214
13255
|
this.resizeObserver.disconnect();
|
|
13215
13256
|
this.resizeObserver = null;
|
|
13216
13257
|
}
|
|
13258
|
+
if (this.boardViewportObserver) {
|
|
13259
|
+
this.boardViewportObserver.disconnect();
|
|
13260
|
+
this.boardViewportObserver = null;
|
|
13261
|
+
}
|
|
13262
|
+
if (this.boardViewportsSubscription) {
|
|
13263
|
+
this.boardViewportsSubscription.unsubscribe();
|
|
13264
|
+
this.boardViewportsSubscription = null;
|
|
13265
|
+
}
|
|
13217
13266
|
if (this.groupIntersectionObserver) {
|
|
13218
13267
|
this.groupIntersectionObserver.disconnect();
|
|
13219
13268
|
this.groupIntersectionObserver = null;
|
|
@@ -14513,6 +14562,18 @@ class EruGridComponent {
|
|
|
14513
14562
|
span += 1;
|
|
14514
14563
|
return span;
|
|
14515
14564
|
}
|
|
14565
|
+
/**
|
|
14566
|
+
* Height the column's card viewport asks for: exactly the loaded cards.
|
|
14567
|
+
* The column's max-height clamps it (the viewport is a shrinkable flex item),
|
|
14568
|
+
* so a column with fewer cards than the cap ends right after the last card
|
|
14569
|
+
* and a fuller one scrolls. Never zero — an empty group keeps one slot so the
|
|
14570
|
+
* column still reads as a column.
|
|
14571
|
+
*/
|
|
14572
|
+
boardColumnBodyHeight(group) {
|
|
14573
|
+
const rows = this.getRowsForGroupSignal(group.id)();
|
|
14574
|
+
const count = Math.max(rows?.length ?? 0, 1);
|
|
14575
|
+
return count * this.boardCardSlot;
|
|
14576
|
+
}
|
|
14516
14577
|
onBoardScrolledIndexChange(firstVisibleIndex, group) {
|
|
14517
14578
|
const rows = this.getRowsForGroupSignal(group.id)();
|
|
14518
14579
|
const totalLoaded = rows.length;
|
|
@@ -14560,7 +14621,7 @@ class EruGridComponent {
|
|
|
14560
14621
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: EruGridComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
14561
14622
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: EruGridComponent, isStandalone: true, selector: "eru-grid", inputs: { gridConfig: "gridConfig", boardCardTemplate: "boardCardTemplate", personCardTemplate: "personCardTemplate", boardCardHeight: "boardCardHeight", boardCardGap: "boardCardGap", boardCardPadding: "boardCardPadding" }, outputs: { rowSelect: "rowSelect", actionClick: "actionClick" }, providers: [EruGridStore, EruGridService,
|
|
14562
14623
|
...MATERIAL_PROVIDERS
|
|
14563
|
-
], viewQueries: [{ propertyName: "rowContainer", first: true, predicate: ["rowContainer"], descendants: true }, { propertyName: "headerScroller", first: true, predicate: ["headerScroller"], descendants: true, read: ElementRef }, { propertyName: "gtScroller", first: true, predicate: ["gtScroller"], descendants: true, read: ElementRef }, { propertyName: "viewport", first: true, predicate: ["vp"], descendants: true }, { propertyName: "groupsViewport", first: true, predicate: ["groupsViewport"], descendants: true }, { propertyName: "groupsScrollContainerEl", first: true, predicate: ["groupsScrollContainer"], descendants: true }, { propertyName: "allViewports", predicate: CdkVirtualScrollViewport, descendants: true }, { propertyName: "headerScrollers", predicate: ["headerScroller"], descendants: true }], ngImport: i0, template: "<!-- <div style=\"background: #f0f0f0; font-size: 12px; border-bottom: 1px solid #ccc;\">\ncurrentPivotScrollIndex {{currentPivotScrollIndex()}} |\nfirstDataRowIndex {{firstDataRowIndex()}} |\nfirstTr {{firstTr}} |\nmaxDepth {{maxDepth()}}\n</div> -->\n<div class=\"incremental-row-container eru-grid\" #rowContainer [class.pivot-mode]=\"gridStore.isPivotMode()\"\n [class.table-mode]=\"!gridStore.isPivotMode() && !isBoardMode()\" [class.board-mode-host]=\"isBoardMode()\">\n <eru-column-design-panel></eru-column-design-panel>\n <!-- Pivot Mode Template -->\n @if (gridStore.isPivotMode()) {\n <ng-container>\n <div class=\"pivot-container\" style=\"display: flex; flex-direction: column; height: 100%;\"\n [style]=\"'--table-min-height: ' + getInitialMinHeightPx() + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <!-- Debug info for first visible row -->\n\n\n <div class=\"pivot-single-table\"\n style=\"height: 100%; width: 100%; overflow: hidden; display: flex; flex-direction: column;\">\n @if (freezeHeader()) {\n <div #headerScroller class=\"header-shell\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n @if(grandTotalPosition() === 'before' && freezeGrandTotal()) {\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n }\n </table>\n </div>\n }\n <!-- Virtual Scrolled Table Body -->\n <div>\n <cdk-virtual-scroll-viewport #vp [itemSize]=\"dataRowHeight()\" class=\"viewport pivot-viewport\"\n [class.apply-cdk-width]=\"applyCdkWidth()\" (scrolledIndexChange)=\"onPivotScroll($event)\"\n (scroll)=\"onBodyScroll($event)\" style=\"overflow: auto;\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n @if (!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n }\n <!-- Table Body with Virtual Scrolling -->\n <tbody class=\"pivot-tbody\">\n\n <tr *cdkVirtualFor=\"let pivotRow of gridStore.pivotDisplayData(); \n trackBy: trackByPivotRowFn; \n let i = index\" class=\"pivot-row\" [class.subtotal-row]=\"pivotRow._isSubtotal\"\n [class.grand-total-row]=\"pivotRow._isGrandTotal\"\n [class.subtotal-bold]=\"pivotRow._isSubtotal && subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"pivotRow._isSubtotal && subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"pivotRow._isSubtotal && subTotalStyle() === 'highlighted'\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\" [style.cursor]=\"cursorOnHover() || null\" [attr.data-pivot-row]=\"i\">\n @if ((!pivotRow._isGrandTotal && freezeGrandTotal() ) || (!freezeGrandTotal() )) {\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.pivot-repeated-value]=\"isRepeatedDimensionValue(i, column.name)\"\n [class.pivot-group-start]=\"isPivotGroupStart(i, column.name)\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content pivot-cell-content\">\n <data-cell [personCardTemplate]=\"personCardTemplate\" [class.aggregation]=\"!!column.aggregationFunction\" [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\" [value]=\"pivotRow[column.name]\"\n [column]=\"column\" [drillable]=\"column.enableDrilldown || false\" [mode]=\"mode()\"\n [isEditable]=\"isEditable()\" [id]=\"'pivot_' + i + '_' + column.name\" [eruGridStore]=\"gridStore\"\n [row]=\"pivotRow\">\n </data-cell>\n </div>\n </td>\n }\n } @else {\n <td [style.height.px]=\"dataRowHeight()\" [attr.colspan]=\"getLeafColumns().length\"> </td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n </div>\n @if (freezeGrandTotal() && grandTotalPosition() === 'after') {\n <div #gtScroller class=\"header-shell gt-shell\" [class.adjust-bottom]=\"!applyCdkWidth()\"\n [class.adjust-bottom-vs]=\"adjustScrollWidth()\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n\n </table>\n </div>\n }\n\n\n </div>\n </div>\n </ng-container>\n } @else if (isBoardMode()) {\n <!-- Board Mode Template -->\n <div class=\"board-view-container\">\n @if(showSortBar()) {\n <div class=\"board-sort-bar\">\n <span class=\"board-sort-label\">Sort by:</span>\n @for (entry of gridStore.sortColumns(); track getFieldName(entry)) {\n <span class=\"board-sort-chip board-sort-chip-active\">\n <span class=\"board-sort-chip-label\">{{getColumnLabel(entry)}}</span>\n <span class=\"board-sort-chip-arrow\" (click)=\"onBoardSortChipToggle($event, entry)\">\n @if(!entry.startsWith('-')) { \u25B2 } @else { \u25BC }\n </span>\n @if(gridStore.sortColumns().length > 1) {\n <span class=\"board-sort-chip-priority\">{{getSortPriority(getFieldName(entry))}}</span>\n }\n <span class=\"board-sort-chip-remove\" (click)=\"onBoardSortChipRemove($event, entry)\">\u2715</span>\n </span>\n }\n <button class=\"board-sort-add-btn\" [matMenuTriggerFor]=\"sortFieldMenu\">\n <mat-icon class=\"board-sort-add-icon\">add</mat-icon> Add field\n </button>\n <mat-menu #sortFieldMenu=\"matMenu\" class=\"board-sort-menu\">\n @for (column of columns(); track column.name) {\n <button mat-menu-item (click)=\"onBoardSortFieldSelect(column)\"\n [disabled]=\"getSortDirection(column.name) !== null\">\n @if(getSortDirection(column.name) !== null) {\n <mat-icon>check</mat-icon>\n } @else {\n <mat-icon></mat-icon>\n }\n {{column.label}}\n </button>\n }\n </mat-menu>\n @if(gridStore.sortColumns().length > 0) {\n <button class=\"board-sort-clear\" (click)=\"onBoardSortClear()\">\u2715 Clear</button>\n }\n </div>\n }\n <div class=\"board-columns-wrapper\" [class.board-columns-nowrap]=\"!boardWrapColumns()\">\n @for (group of groups(); track group.id) {\n <div class=\"board-column\" [class.board-column-accented]=\"!!boardGroupColor(group)\"\n [style.--board-group-color]=\"boardGroupColor(group)\">\n <div class=\"column-header\">\n <!-- Render the group value through the same read-only cell renderer a\n data cell uses, so the grouped field's datatype formats itself\n (status/tag pills, dates, numbers) instead of printing raw text. -->\n @if (groupByColumn(); as gcol) {\n <span class=\"column-header-title column-header-title-cell\">\n <data-cell\n [eruGridStore]=\"gridStore\"\n [column]=\"gcol\"\n [columnDatatype]=\"gcol.datatype\"\n [columnName]=\"gcol.name\"\n [value]=\"group.title\"\n [id]=\"'board-group-' + group.id\"\n [fieldSize]=\"0\"\n [isEditable]=\"false\"\n [mode]=\"'board-group-header'\">\n </data-cell>\n </span>\n } @else {\n <span class=\"column-header-title\">{{ group.title }}</span>\n }\n <span class=\"column-header-count\">{{ group.currentLoadedRows || 0 }} of {{ group.totalRowCount || 0 }}</span>\n </div>\n <cdk-virtual-scroll-viewport [itemSize]=\"boardCardSlot\" class=\"board-column-body\"\n (scrolledIndexChange)=\"onBoardScrolledIndexChange($event, group)\">\n <div\n *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id)(); templateCacheSize: 0\"\n class=\"board-card-container\"\n [class.selected]=\"isBoardCardActive(row)\"\n [class.show-row-lines]=\"showRowLines()\"\n [style.height.px]=\"boardCardOuterHeight\"\n [style.padding.px]=\"boardCardPadding\"\n [style.marginBottom.px]=\"boardCardGap\"\n [style.cursor]=\"cursorOnHover() || null\"\n (click)=\"emitRowSelect(row, 'board', group)\">\n <!-- Custom template when consumer provides boardCardTemplate; default card otherwise -->\n <ng-container\n *ngTemplateOutlet=\"boardCardTemplate ?? defaultBoardCard;\n context: { $implicit: row, columns: visibleBoardFields(), group: group }\">\n </ng-container>\n </div>\n </cdk-virtual-scroll-viewport>\n @if (group.isLoading) {\n <div class=\"board-ghost-card\">\n <div class=\"board-ghost-line\"></div>\n <div class=\"board-ghost-line board-ghost-line--short\"></div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else {\n\n <!-- Table Mode Template -->\n <ng-template #excelDownloadIcon>\n <svg class=\"excel-download-icon\" title=\"Download Excel\" (click)=\"onExcelDownloadClick($event)\"\n xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" width=\"24px\" height=\"24px\">\n <path fill=\"#169154\" d=\"M29,6H15.744C14.781,6,14,6.781,14,7.744v7.259h15V6z\" />\n <path fill=\"#18482a\" d=\"M14,33.054v7.202C14,41.219,14.781,42,15.743,42H29v-8.946H14z\" />\n <path fill=\"#0c8045\" d=\"M14 15.003H29V24.005000000000003H14z\" />\n <path fill=\"#17472a\" d=\"M14 24.005H29V33.055H14z\" />\n <g>\n <path fill=\"#29c27f\" d=\"M42.256,6H29v9.003h15V7.744C44,6.781,43.219,6,42.256,6z\" />\n <path fill=\"#27663f\" d=\"M29,33.054V42h13.257C43.219,42,44,41.219,44,40.257v-7.202H29z\" />\n <path fill=\"#19ac65\" d=\"M29 15.003H44V24.005000000000003H29z\" />\n <path fill=\"#129652\" d=\"M29 24.005H44V33.055H29z\" />\n </g>\n <path fill=\"#0c7238\"\n d=\"M22.319,34H5.681C4.753,34,4,33.247,4,32.319V15.681C4,14.753,4.753,14,5.681,14h16.638 C23.247,14,24,14.753,24,15.681v16.638C24,33.247,23.247,34,22.319,34z\" />\n <path fill=\"#fff\"\n d=\"M9.807 19L12.193 19 14.129 22.754 16.175 19 18.404 19 15.333 24 18.474 29 16.123 29 14.013 25.07 11.912 29 9.526 29 12.719 23.982z\" />\n </svg>\n </ng-template>\n @if(showExcelDownload() && !showGroupBar()) {\n <div class=\"excel-download-bar\">\n <ng-container *ngTemplateOutlet=\"excelDownloadIcon\"></ng-container>\n </div>\n }\n <!-- Scrollable groups container \u2014 plain iteration avoids CDK fixed-height estimation errors -->\n <div #groupsScrollContainer class=\"groups-scroll-container\" (scroll)=\"onGroupsViewportScroll($event)\">\n\n @for (group of groups(); track trackByGroupFn($index, group); let i = $index) {\n <div class=\"group-container\"\n [attr.data-group-id]=\"group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id\">\n <!-- Combined sticky header with group info and table -->\n <div style=\"\n background:var(--grid-surface);\n position: sticky;\n top: 0;\n z-index: 115;\n \">\n @if(showGroupBar()) {\n <div class=\"group-header-row\">\n <div class=\"custom-collapse-header\" (click)=\"toggleGroupCollapse(group.id)\">\n <span class=\"collapse-arrow\" [ngClass]=\"{\n 'rotate-arrow': group.isExpanded,\n }\">\u25BC</span>\n <span class=\"f-12\">\n {{ group?.title || \"\" }}\n {{ group?.currentLoadedRows || 0 }} -\n {{ group?.totalRowCount || 0 }} rows...</span>\n @if(groupByField() && isSortable()) {\n <span class=\"group-sort-indicator\">\n <span class=\"sort-triangles\">\n <span class=\"sort-tri sort-tri-up\" [class.sort-tri-active]=\"getSortDirection(groupByField()!) === 'asc'\"\n (click)=\"onGroupSortToggle($event, 'asc')\"></span>\n <span class=\"sort-tri sort-tri-down\"\n [class.sort-tri-active]=\"getSortDirection(groupByField()!) === 'desc'\"\n (click)=\"onGroupSortToggle($event, 'desc')\"></span>\n </span>\n </span>\n }\n </div>\n @if(i === 0 && showExcelDownload()) {\n <ng-container *ngTemplateOutlet=\"excelDownloadIcon\"></ng-container>\n }\n </div>\n }\n\n @if(freezeHeader() && (group.isExpanded || !showGroupBar())) {\n <div #headerScroller class=\"header-shell\" [attr.data-group-id]=\"'header-shell-' + group.id\"\n [style]=\"'--table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <table class=\"eru-grid-table\" [class.freeze-header]=\"freezeHeader()\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"tableColGroup\"></ng-container>\n <ng-container *ngTemplateOutlet=\"tableHeader\"></ng-container>\n <!-- Grand Total row after sticky header (position: before) - only for first group -->\n @if(enableColumnGrandTotal() && grandTotalPositionColumn() === 'before' && hasGrandTotalData() && i === 0) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n </tbody>\n }\n <!-- Subtotal row after sticky header (position: before) -->\n @if(enableColumnSubtotals() && subtotalPositionColumn() === 'before' && hasSubtotalData(group)) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n </tbody>\n }\n </table>\n </div>\n }\n </div>\n @if(group.isExpanded || !showGroupBar()) {\n <ng-container>\n <cdk-virtual-scroll-viewport [attr.data-group-id]=\"group.id\" [itemSize]=\"dataRowHeight()\" class=\"viewport table-viewport\"\n (scrolledIndexChange)=\"onScroll($event, group)\" (scroll)=\"onTableBodyScroll($event)\"\n [style]=\"'--table-height: ' + getGroupContentHeight(group.id) + 'px; --table-min-height: ' + getGroupContentHeight(group.id) + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <div class=\"table-wrapper\">\n <table class=\"eru-grid-table\" [class.show-column-lines]=\"showColumnLines()\"\n [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"tableColGroup\"></ng-container>\n @if(!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"tableHeader\"></ng-container>\n }\n <!-- Grand Total row after normal header (position: before) - only for first group -->\n @if(!freezeHeader() && enableColumnGrandTotal() && grandTotalPositionColumn() === 'before' &&\n hasGrandTotalData() && i === 0) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n </tbody>\n }\n <!-- Subtotal row after normal header (position: before) -->\n @if(!freezeHeader() && enableColumnSubtotals() && subtotalPositionColumn() === 'before' &&\n hasSubtotalData(group)) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n </tbody>\n }\n <tbody>\n @if (columns(); as columnsList) {\n <!-- <tr *ngIf=\"groupItem.type === 'table-header' && groups().length > 1\" style=\"background:#fafafa\">\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isGroupSelected(groupItem.group?.id || '')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleGroupSelection($event, groupItem.group?.id || '')\"\n >\n </th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn;let i =index\"\n style=\"text-align: center;\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"true\"\n [columnConfig]=\"column\"\n [columnDraggable]=\"i\"\n class=\"column-header\">\n <div class=\"column-drag-handle\"></div>\n {{column.label}} {{column.symbol}}\n </th>\n </tr> -->\n <!-- @if(getRowsForGroup(group.id).length > 0 && group.isExpanded) { -->\n <!-- *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id)(); \n trackBy: trackByRowFn; \n let i = index\" -->\n <!-- @for(row of getRowsForGroupSignal(group.id)(); track trackByRowFn($index, row); let i = $index) { -->\n <ng-container\n *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id)(); trackBy: trackByRowFn; let i = index\">\n <tr class=\"row-item\" [attr.data-row-id]=\"i\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\" [style.cursor]=\"cursorOnHover() || null\" (click)=\"emitRowSelect(row, 'table', group)\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\" style=\"text-align: center;\">\n <input type=\"checkbox\" [checked]=\"isRowSelected(row?.entity_id)\"\n (change)=\"toggleRowSelection($event, row)\">\n </td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <ng-container\n *ngTemplateOutlet=\"actionCell; context: { $implicit: row, mode: 'table', group: group }\"></ng-container>\n </td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\" (click)=\"toggleRowExpand(row, i, $event)\">\n <mat-icon class=\"row-expand-icon\" [class.expanded]=\"isRowExpanded(row, i)\">chevron_right</mat-icon>\n </td>\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <td #cell [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n class=\"data-cell\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\"\n [matTooltipClass]=\"'error-message'\" [matTooltip]=\"datacell.error()?'Error: ' + datacell.error():''\"\n matTooltipPosition=\"below\">\n <div class=\"cell-content\">\n <data-cell #datacell [personCardTemplate]=\"personCardTemplate\" [td]=cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\" [value]=\"(row?.['entity_data']?.[column.name] ?? row?.[column.name]) || ''\" [column]=\"column\"\n [mode]=\"mode()\" [isEditable]=\"isEditable() && column.editable !== false && column.editable !== 'false'\" [drillable]=\"column.enableDrilldown || false\"\n [id]=\"i + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"row\"></data-cell>\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <ng-container\n *ngTemplateOutlet=\"actionCell; context: { $implicit: row, mode: 'table', group: group }\"></ng-container>\n </td>\n }\n </tr>\n @if(hasHiddenColumns() && isRowExpanded(row, i)) {\n <tr class=\"row-detail\">\n <td class=\"row-detail-cell\" [attr.colspan]=\"rowDetailColspan()\">\n <div class=\"row-detail-grid\">\n @for (hiddenCol of hiddenColumns(); track trackByColumnFn($index, hiddenCol)) {\n <div class=\"row-detail-field\">\n <span class=\"row-detail-label\">{{hiddenCol.label}}</span>\n <div class=\"row-detail-value\">\n <data-cell [fieldSize]=\"hiddenCol.field_size\" [columnDatatype]=\"hiddenCol.datatype\"\n [columnName]=\"hiddenCol.name\" [value]=\"(row?.['entity_data']?.[hiddenCol.name] ?? row?.[hiddenCol.name]) || ''\"\n [column]=\"hiddenCol\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [drillable]=\"hiddenCol.enableDrilldown || false\"\n [id]=\"'detail_' + i + '_' + hiddenCol.name\" [eruGridStore]=\"gridStore\" [row]=\"row\"></data-cell>\n </div>\n </div>\n }\n </div>\n </td>\n </tr>\n }\n </ng-container>\n <!-- } -->\n <!-- } -->\n @if(group.isLoading && (group.isExpanded || !showGroupBar())) {\n @for(i of [].constructor(ghostRows()); let j = $index; track j) {\n <tr class=\"ghost-loading-row\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column ghost-cell-container\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n class=\"ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column ghost-cell-container\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n </tr>\n }\n }\n <!-- <tr\n *ngIf=\"getRowsForGroup(group.id).length === 0 && !group.isExpanded\"\n class=\"group-separator\"\n >\n <td [attr.colspan]=\"groupSeperatorColSpan()\" class=\"separator-cell\"></td>\n </tr> -->\n <!-- Subtotal row at end of group (position: after) -->\n @if(enableColumnSubtotals() && subtotalPositionColumn() === 'after' && hasSubtotalData(group)) {\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n }\n <!-- Grand Total row at end of group (position: after) - only for last group -->\n @if(enableColumnGrandTotal() && grandTotalPositionColumn() === 'after' && hasGrandTotalData() && i ===\n groups().length - 1) {\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n }\n }\n </tbody>\n </table>\n </div>\n </cdk-virtual-scroll-viewport>\n </ng-container>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Pivot Table Header Template -->\n<ng-template #pivotTableHead>\n <thead [class.eru-wrap-headers]=\"wrapHeaders()\">\n @if (hasNestedHeaders()) {\n <ng-container>\n @for (headerRow of getHeaderRows(); track headerRow; let rowIndex = $index) {\n <tr class=\"pivot-header pivot-header-container\" [class.pivot-header-level]=\"'level-' + rowIndex\">\n @for (header of headerRow; track trackByHeaderFn($index, header); let colIndex = $index) {\n <th [attr.colspan]=\"header.colspan\" [attr.rowspan]=\"header.rowspan\"\n [resizeColumn]=\"isResizablePivotHeader(header)\"\n [columnConfig]=\"getFieldForPivotHeader(header) || $any(header)\"\n class=\"column-header pivot-column-header nested-header\"\n [class.row-dimension-header]=\"isRowDimensionHeader(header)\"\n [class.column-dimension-header]=\"!isRowDimensionHeader(header)\" [class.expanded]=\"header.isExpanded\"\n [class.collapsed]=\"!header.isExpanded\" [class.sticky-column]=\"isStickyColumn(header.name, colIndex)\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === designTargetFor($any(header))\"\n [style.position]=\"isStickyColumn(header.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(header.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(header.name, colIndex) ? 100 : 1\"\n [style.min-height.px]=\"headerRowHeight()\" style=\"height: auto; padding: 8px 6px;\">\n <div class=\"header-content\">\n\n <data-cell [fieldSize]=\"header.field_size\" [columnDatatype]=\"header.dataType\" [columnName]=\"header.name\"\n [value]=\"header.label\" [column]=\"header\" [frozenGrandTotalCell]=\"true\"\n [drillable]=\"header.enableDrilldown || false\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + $index + '_' + header.name\" [eruGridStore]=\"gridStore\" [row]=\"header\">\n </data-cell>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\"\n [title]=\"isAggregationHeader($any(header)) ? 'Edit aggregation' : 'Edit column'\"\n (click)=\"onHeaderDesignClick($event, $any(header))\">tune</mat-icon>\n }\n <!-- <span class=\"header-label header-wrap-text\">{{header.label}}</span> -->\n <!-- <button *ngIf=\"!isRowDimensionHeader(header)\"\n class=\"collapse-toggle-btn\"\n [title]=\"header.isExpanded ? 'Collapse group' : 'Expand group'\"\n (click)=\"toggleColumnGroup(header.groupKey)\"\n type=\"button\">\n <span class=\"collapse-icon\">+</span>\n </button> -->\n </div>\n </th>\n }\n </tr>\n }\n </ng-container>\n } @else {\n <!-- Simple header fallback -->\n <ng-container>\n <tr class=\"pivot-header\" [class.freeze-header-enabled]=\"freezeHeader()\">\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <th [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\" [columnConfig]=\"column\"\n class=\"column-header pivot-column-header\" [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === designTargetFor(column)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 100 : 1\"\n [style.min-height.px]=\"headerRowHeight()\" style=\"height: auto;padding: 8px 6px\">\n <!-- Label and control laid out as a row: the label truncates, the\n control keeps its place. Left as a bare text node the long\n aggregation labels pushed the icon past the cell edge, where\n `overflow: hidden` clipped it out of sight entirely. -->\n <div class=\"pivot-header-content\">\n <!-- Deliberately not `.column-label`: that class carries the\n wrap-headers rule, which broke these labels onto one word per\n line. This header truncates, as it did before. -->\n <span class=\"pivot-header-label\">{{column.label}}</span>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\"\n [title]=\"isAggregationHeader(column) ? 'Edit aggregation' : 'Edit column'\"\n (click)=\"onHeaderDesignClick($event, column)\">tune</mat-icon>\n }\n </div>\n </th>\n }\n </tr>\n </ng-container>\n }\n\n </thead>\n</ng-template>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #pivotColGroup>\n <colgroup>\n @for (column of getLeafColumns(); track trackByColumnFn($index, column)) {\n <col\n [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n </colgroup>\n</ng-template>\n\n<ng-template #pivotGrandTotal>\n <tbody class=\"pivot-tbody\">\n @for (pivotRow of gridStore.pivotGrandTotalData(); track trackByPivotRowFn($index, pivotRow); let i = $index) {\n <tr class=\"pivot-row grand-total-row\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\" [attr.data-pivot-row]=\"i\">\n <!-- <td colspan=\"20\">{{pivotRow | json}}</td> -->\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\" [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\" class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\" [style.height.px]=\"50\" [attr.xx]=\"i\">\n <div class=\"cell-content pivot-cell-content\">\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\" [column]=\"column\" [frozenGrandTotalCell]=\"true\"\n [drillable]=\"column.enableDrilldown || false\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"pivotRow\">\n </data-cell>\n </div>\n </td>\n }\n </tr>\n }\n </tbody>\n</ng-template>\n\n<!-- \u2500\u2500\u2500 Action column cell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n One template for both column positions. With no `config.actions` set it\n falls back to the single more_horiz icon the column has always shown, so\n grids that only listen to the store's actionClick signal keep working.\n Context: { $implicit: Row, mode: 'table' | 'board', group?: RowGroup }\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #actionCell let-row let-mode=\"mode\" let-group=\"group\">\n @if(!hasConfiguredActions()) {\n <mat-icon (click)=\"onActionClick($event, row, undefined, mode || 'table', group)\">more_horiz</mat-icon>\n } @else if(actionDisplayType() === 'kebab') {\n @if(visibleActionsFor(row).length > 0) {\n <mat-icon class=\"action-kebab\" [matMenuTriggerFor]=\"rowActionMenu\"\n [matMenuTriggerData]=\"{ row: row, mode: mode || 'table', group: group }\"\n (click)=\"$event.stopPropagation()\">more_vert</mat-icon>\n }\n } @else {\n <div class=\"action-icons\">\n @for(action of visibleActionsFor(row); track action.action_name) {\n <mat-icon class=\"action-icon\" [matTooltip]=\"action.action_name\" matTooltipPosition=\"above\"\n (click)=\"onActionClick($event, row, action, mode || 'table', group)\">{{action.action_icon || 'play_arrow'}}</mat-icon>\n }\n </div>\n }\n</ng-template>\n\n<!-- Kebab menu shared by every row; the row is passed through matMenuTriggerData. -->\n<mat-menu #rowActionMenu=\"matMenu\" class=\"eru-grid-action-menu\">\n <ng-template matMenuContent let-row=\"row\" let-mode=\"mode\" let-group=\"group\">\n @for(action of visibleActionsFor(row); track action.action_name) {\n <button mat-menu-item (click)=\"onActionClick($event, row, action, mode || 'table', group)\">\n <mat-icon>{{action.action_icon || 'play_arrow'}}</mat-icon>\n <span>{{action.action_name}}</span>\n </button>\n }\n </ng-template>\n</mat-menu>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #tableColGroup>\n <colgroup>\n @if(gridStore.configuration().config.allowSelection) {\n <col style=\"width: 40px; min-width: 40px; max-width: 40px;\">\n }\n @if(shouldShowActionColumn('before')) {\n <col\n [style]=\"'width: ' + actionColumnWidth() + 'px !important; min-width: ' + actionColumnWidth() + 'px !important; max-width: ' + actionColumnWidth() + 'px !important;'\">\n }\n @if(hasHiddenColumns()) {\n <col style=\"width: 40px !important; min-width: 40px !important; max-width: 40px !important;\">\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <col\n [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n @if(shouldShowActionColumn('after')) {\n <col\n [style]=\"'width: ' + actionColumnWidth() + 'px !important; min-width: ' + actionColumnWidth() + 'px !important; max-width: ' + actionColumnWidth() + 'px !important;'\">\n }\n </colgroup>\n</ng-template>\n\n\n<ng-template #tableHeader>\n\n <thead [class.eru-wrap-headers]=\"wrapHeaders()\">\n <tr>\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column column-header table-column-header\">\n <input type=\"checkbox\" [checked]=\"isAllGroupsSelected()\" (change)=\"toggleAllGroups($event)\">\n </th>\n }\n @if(shouldShowActionColumn('before')) {\n <th class=\"action-column column-header table-column-header\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">Action</th>\n }\n @if(hasHiddenColumns()) {\n <th class=\"row-expand-toggle column-header table-column-header\"></th>\n }\n @for (column of visibleColumns(); track trackByColumnFn(i, column); let i = $index) {\n <th [style.width.px]=\"column.field_size\" [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [columnConfig]=\"column\" [index]=\"i\"\n [columnDraggable]=\"gridStore.isFeatureEnabled('columnReorderable') ? i : null\"\n [style.minWidth.px]=\"column.field_size\" class=\"column-header table-column-header\"\n [class.sortable-header]=\"isSortable()\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === column.name\"\n [class.sort-asc]=\"isSortable() && getSortDirection(column.name) === 'asc'\"\n [class.sort-desc]=\"isSortable() && getSortDirection(column.name) === 'desc'\">\n @if(gridStore.isFeatureEnabled('columnReorderable')) {\n <div class=\"column-drag-handle\"></div>\n }\n <span class=\"column-label\" [title]=\"column.tool_tip || column.description || ''\">{{column.label}}</span>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\" title=\"Edit column\" (click)=\"onHeaderDesignClick($event, column)\">tune</mat-icon>\n }\n @if(isSortable()) {\n <span class=\"sort-indicator\">\n <span class=\"sort-triangles\">\n <span class=\"sort-tri sort-tri-up\" [class.sort-tri-active]=\"getSortDirection(column.name) === 'asc'\"\n (click)=\"onSortColumn($event, column, 'asc')\"></span>\n <span class=\"sort-tri sort-tri-down\" [class.sort-tri-active]=\"getSortDirection(column.name) === 'desc'\"\n (click)=\"onSortColumn($event, column, 'desc')\"></span>\n </span>\n @if(getSortPriority(column.name) !== null && gridStore.sortColumns().length > 1) {\n <span class=\"sort-priority\">{{getSortPriority(column.name)}}</span>\n }\n </span>\n }\n </th>\n }\n @if(shouldShowActionColumn('after')) {\n <th class=\"action-column column-header table-column-header\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">Action</th>\n }\n </tr>\n </thead>\n</ng-template>\n\n<!-- Table Subtotal Row Template -->\n<ng-template #tableSubtotal let-group=\"group\">\n <tr class=\"subtotal-row\" [class.subtotal-bold]=\"subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"subTotalStyle() === 'highlighted'\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\"></td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\"></td>\n }\n @for(column of visibleColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"subtotal-cell\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content\">\n @if(colIndex === 0 && getSubtotalValue(group, column.name) === null) {\n <span class=\"subtotal-label\">{{subtotalLabel()}}</span>\n } @else {\n @if(getSubtotalValue(group, column.name) !== null) {\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getSubtotalValue(group, column.name)\" [column]=\"column\" [mode]=\"mode()\" [isEditable]=\"false\"\n [id]=\"'subtotal_' + group.id + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"group.subtotal\">\n </data-cell>\n }\n }\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n </tr>\n</ng-template>\n\n<!-- Table Grand Total Row Template -->\n<ng-template #tableGrandTotal>\n <tr class=\"grand-total-row\" [class.grand-total-bold]=\"grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"grandTotalStyle() === 'highlighted'\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\"></td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\"></td>\n }\n @for(column of visibleColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"grand-total-cell\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content\">\n @if(colIndex === 0 && getGrandTotalValue(column.name) === null) {\n <span class=\"grand-total-label\">Grand Total</span>\n } @else {\n @if(getGrandTotalValue(column.name) !== null) {\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getGrandTotalValue(column.name)\" [column]=\"column\" [mode]=\"mode()\" [isEditable]=\"false\"\n [id]=\"'grandtotal_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"gridStore.rowGrandTotal()\">\n </data-cell>\n }\n }\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n </tr>\n</ng-template>\n\n<!-- \u2500\u2500\u2500 Default board card template \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Used when no boardCardTemplate is passed to <eru-grid>.\n Context: { $implicit: Row, columns: Field[], group: RowGroup }\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #defaultBoardCard let-row let-columns=\"columns\" let-group=\"group\">\n <mat-card class=\"board-card\">\n <mat-card-content>\n @for (column of columns; track column.name) {\n @if ((row?.entity_data?.[column.name] ?? row?.[column.name]) !== undefined) {\n <div class=\"board-card-field\">\n <span class=\"board-field-label\">{{ column.label }}</span>\n <data-cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [column]=\"column\"\n [value]=\"row?.entity_data?.[column.name] ?? row?.[column.name]\"\n [id]=\"row?.entity_id + '_' + column.name\"\n [eruGridStore]=\"gridStore\"\n [mode]=\"'board'\"\n [row]=\"row\">\n </data-cell>\n </div>\n }\n }\n </mat-card-content>\n <mat-card-actions align=\"end\">\n <button mat-icon-button (click)=\"onActionClick($event, row)\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n </mat-card-actions>\n </mat-card>\n</ng-template>", styles: ["@charset \"UTF-8\";:root{--grid-primary: #6750a4;--grid-on-primary: #ffffff;--grid-surface: #fef7ff;--grid-surface-variant: #e7e0ec;--grid-surface-container: #f3edf7;--grid-surface-container-high: #ede7f0;--grid-on-surface: #1d1b20;--grid-on-surface-variant: #49454f;--grid-outline: #79757f;--grid-outline-variant: #cac4d0;--grid-error: #ba1a1a;--grid-error-container: #ffdad6}:host,eru-grid{display:block!important;width:100%;height:100%;flex:1 1 0%;min-height:var(--grid-height, 300px);font-family:var(--grid-font-family);--grid-font-family: \"Poppins\", \"Roboto\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--grid-font-size-body: 12px;--grid-font-size-caption: 12px !important;--grid-line-height-body: 1;--grid-aggregation-text-align: right;--grid-number-text-align: right;--grid-spacing-xxs: 2px;--grid-spacing-xs: 4px;--grid-spacing-sm: 8px;--grid-spacing-md: 16px;--grid-spacing-lg: 24px;--grid-border-radius: 4px;--grid-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 1px 3px 1px rgba(0, 0, 0, .15);--grid-elevation-2: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 2px 6px 2px rgba(0, 0, 0, .15);--grid-row-hover: var(--grid-surface-variant);--grid-row-selected: var(--grid-surface-container-high);--grid-zebra-odd: transparent;--grid-zebra-even: transparent;--grid-focus-ring: var(--grid-primary);--grid-header-font-weight: 500;--grid-header-text-transform: none;--grid-header-letter-spacing: normal;--grid-header-font-size: var(--grid-font-size-caption);--grid-header-padding-x: 8px;--grid-header-padding-y: 12px;--grid-font-feature-numeric: normal;--grid-cell-padding-x: var(--grid-spacing-xs);--grid-cell-padding-y: var(--grid-spacing-xxs);--grid-tint-subtle: rgba(0, 0, 0, .025);--grid-tint-soft: rgba(0, 0, 0, .045);--grid-tint-strong: rgba(0, 0, 0, .08);--grid-radius-outer: 0;--grid-shadow-outer: none;--grid-divider-color: var(--grid-outline-variant);--grid-divider-width: 1px;--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface);--grid-pill-radius: 999px;--grid-pill-padding-y: 3px;--grid-pill-padding-x: 10px;--grid-pill-font-size: 11px;--grid-pill-font-weight: 500;--grid-priority-dot-size: 8px;--grid-avatar-size: 24px;--grid-avatar-font-size: 10px;--grid-avatar-font-weight: 600;border-radius:var(--grid-radius-outer);box-shadow:var(--grid-shadow-outer)}eru-grid[data-preset=default]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: uppercase;--grid-header-letter-spacing: .06em;--grid-header-font-size: 11px;--grid-header-padding-y: 12px;--grid-header-padding-x: 14px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 14px;--grid-row-hover: var(--grid-tint-subtle);--grid-divider-color: var(--grid-tint-soft);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=modern]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: none;--grid-header-letter-spacing: normal;--grid-header-font-size: 13px;--grid-header-padding-y: 16px;--grid-header-padding-x: 18px;--grid-cell-padding-y: 16px;--grid-cell-padding-x: 18px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-radius-outer: 12px;--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 4px;--grid-pill-padding-x: 12px}eru-grid[data-preset=compact]{--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface);--grid-header-font-weight: 600;--grid-header-text-transform: none;--grid-header-font-size: 11px;--grid-header-padding-y: 4px;--grid-header-padding-x: 8px;--grid-cell-padding-y: 3px;--grid-cell-padding-x: 8px;--grid-font-size-body: 11px;--grid-row-hover: var(--grid-tint-subtle);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 1px;--grid-pill-padding-x: 6px;--grid-pill-font-size: 10px}eru-grid[data-preset=bold]{--grid-header-bg: var(--grid-surface-container-high);--grid-header-color: var(--grid-on-surface);--grid-header-font-weight: 700;--grid-header-text-transform: none;--grid-header-font-size: 13px;--grid-header-padding-y: 14px;--grid-header-padding-x: 12px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 12px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-strong);--grid-divider-width: 1px;--grid-radius-outer: 2px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=financial]{--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: uppercase;--grid-header-letter-spacing: .08em;--grid-header-font-size: 11px;--grid-header-padding-y: 12px;--grid-header-padding-x: 14px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 14px;--grid-zebra-odd: transparent;--grid-zebra-even: var(--grid-tint-subtle);--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=elevated]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 600;--grid-header-text-transform: none;--grid-header-font-size: 12px;--grid-header-padding-y: 16px;--grid-header-padding-x: 18px;--grid-cell-padding-y: 14px;--grid-cell-padding-x: 18px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-radius-outer: 16px;--grid-shadow-outer: 0 1px 3px rgba(0, 0, 0, .06), 0 10px 28px rgba(0, 0, 0, .07);--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 4px;--grid-pill-padding-x: 12px;overflow:hidden}.group-container{padding-bottom:8px}.column-header.design-clickable .design-edit-icon{font-size:16px;width:16px;height:16px;margin-left:4px;opacity:.45;vertical-align:middle;cursor:pointer}.column-header.design-clickable:hover .design-edit-icon,.column-header.design-clickable .design-edit-icon:hover{opacity:1}.column-header.design-selected{background-color:var(--grid-primary-light, rgba(63, 81, 181, .12))}.pivot-column-header .pivot-header-content{display:flex;align-items:center;justify-content:center;gap:4px;min-width:0}.pivot-column-header .pivot-header-content .pivot-header-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.pivot-column-header .pivot-header-content .design-edit-icon,.pivot-column-header .header-content .design-edit-icon{flex:0 0 auto}.pivot-column-header .header-content data-cell,.pivot-column-header .header-content data-cell *{color:inherit!important}.incremental-row-container{width:100%;height:100%;min-height:var(--grid-height, 300px);max-height:none;overflow:auto;position:relative;background-color:var(--grid-surface);border-radius:var(--grid-border-radius);font-family:var(--grid-font-family)}.viewport{height:100%;min-height:300px;overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface);scrollbar-gutter:stable}.viewport.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.groups-viewport{height:100%;min-height:300px}.groups-scroll-container{height:var(--grid-height, 600px);overflow-y:auto;overflow-x:hidden}.table-viewport{background-color:var(--grid-surface);height:var(--table-height, auto);min-height:var(--table-min-height, 100px);overflow-x:auto;overflow-y:auto}.pivot-viewport{min-height:var(--table-min-height, 300px);overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface)}.pivot-viewport .cdk-virtual-scroll-content-wrapper{width:auto;height:auto}.table-wrapper{min-width:100%;overflow-x:visible}.incremental-row-container .eru-grid-table,.eru-grid-table{width:100%!important;border-collapse:separate;border-spacing:0;table-layout:fixed!important;background-color:var(--grid-surface);color:var(--grid-on-surface);font-family:var(--grid-font-family);font-size:var(--grid-font-size-body);line-height:var(--grid-line-height-body)}.eru-grid-table th,.eru-grid-table td{text-align:left;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;color:var(--grid-on-surface);min-width:0;max-width:100%!important;box-sizing:border-box;position:relative}.eru-grid-table th{background-color:var(--grid-header-bg, var(--grid-surface-container))}thead.eru-wrap-headers th{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;height:auto}thead.eru-wrap-headers th .column-label,thead.eru-wrap-headers th .header-label{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;word-break:break-word;overflow-wrap:anywhere}.eru-grid-table tbody td{background-color:transparent}.eru-grid-table thead{background-color:var(--grid-header-bg, var(--grid-surface-container));transform:translateZ(0);will-change:transform;backface-visibility:hidden}.eru-grid-table thead.freeze-header-enabled{position:sticky!important;top:0!important;z-index:100!important}.eru-grid-table thead th{background-color:var(--grid-header-bg, var(--grid-surface-container));color:var(--grid-header-color, var(--grid-on-surface));font-family:var(--grid-font-family);font-weight:var(--grid-header-font-weight);font-size:var(--grid-header-font-size)}.checkbox-column{width:50px;min-width:50px;max-width:50px;text-align:center;background-color:var(--grid-surface-container)}.checkbox-column input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--grid-primary);border-radius:var(--grid-border-radius)}.checkbox-column input[type=checkbox]:focus{outline:2px solid var(--grid-primary);outline-offset:2px}.action-column{text-align:center;background-color:var(--grid-surface-container)}.action-column mat-icon{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--grid-on-surface-variant);cursor:pointer}.action-column mat-icon:hover{color:var(--grid-primary)}.action-column .action-icons{display:flex;align-items:center;justify-content:center;gap:6px;overflow-x:auto;scrollbar-width:none}.action-column .action-icons::-webkit-scrollbar{display:none}.action-column .action-icon{flex:0 0 auto}.eru-grid-action-menu .mat-mdc-menu-item mat-icon{margin-right:8px;font-size:18px;width:18px;height:18px;line-height:18px;color:var(--grid-on-surface-variant)}.group-header{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-size:var(--grid-font-size-caption);font-weight:500;border-bottom:1px solid var(--grid-outline);cursor:pointer;transition:background-color .2s ease}.group-header:hover{background-color:var(--grid-surface-container-high)}.group-header .group-title{font-weight:600;color:var(--grid-primary)}.group-header .group-row-count{color:var(--grid-on-surface-variant);font-size:var(--grid-font-size-caption);margin-left:var(--grid-spacing-sm)}.row-item{background-color:var(--grid-surface);transition:background-color .15s ease}.row-item:nth-child(odd){background-color:var(--grid-zebra-odd, var(--grid-surface))}.row-item:nth-child(2n){background-color:var(--grid-zebra-even, var(--grid-surface))}.row-item:hover{background-color:var(--grid-row-hover)}.required-toggle-row{background-color:var(--grid-surface-container, #f3edf7);border-bottom:1px solid var(--grid-outline-variant, #cac4d0)}.required-toggle-row .required-toggle-cell{padding:4px 8px!important;text-align:center;vertical-align:middle;position:relative}.required-toggle-row .required-toggle-cell .required-label{position:absolute;top:2px;left:4px;font-size:10px;color:var(--grid-on-surface-variant, #49454f);font-weight:400;text-transform:lowercase}.required-toggle-row .required-toggle-cell mat-checkbox{display:flex;justify-content:center;align-items:center}.table-column-header{padding:var(--grid-header-padding-y) var(--grid-header-padding-x)}.column-header{font-weight:var(--grid-header-font-weight);text-transform:var(--grid-header-text-transform);letter-spacing:var(--grid-header-letter-spacing);text-align:center!important;font-size:var(--grid-header-font-size);position:relative;-webkit-user-select:none;user-select:none;background-color:var(--grid-header-bg, var(--grid-surface-container));color:var(--grid-header-color, var(--grid-on-surface))}.column-header:hover{background-color:var(--grid-header-hover-bg, var(--grid-surface-container-high))}.column-drag-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:grab;opacity:0;transition:opacity .2s ease,background-color .2s ease;z-index:2;display:flex;align-items:center;justify-content:center;border-right:1px solid transparent}.column-drag-handle:after{content:\"\\22ee\\22ee\";font-size:14px;color:var(--grid-on-surface-variant);transform:rotate(90deg)}.column-drag-handle:hover{background-color:var(--grid-surface-container-high);border-right-color:var(--grid-outline)}.column-header:hover .column-drag-handle{opacity:1}.column-drag-handle:active{cursor:grabbing}.sortable-header{cursor:pointer}.sortable-header .column-label{flex:1}.sortable-header .sort-indicator{display:inline-flex;align-items:center;gap:2px;margin-left:4px;cursor:pointer;vertical-align:middle;opacity:0;transition:opacity .15s ease}.sortable-header .sort-indicator .sort-triangles{display:flex;flex-direction:column;align-items:center;gap:2px}.sortable-header .sort-indicator .sort-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;cursor:pointer;transition:border-color .15s ease}.sortable-header .sort-indicator .sort-tri-up{border-bottom:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.sortable-header .sort-indicator .sort-tri-down{border-top:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.sortable-header .sort-indicator .sort-tri-active{opacity:1}.sortable-header .sort-indicator .sort-tri-active.sort-tri-up{border-bottom-color:var(--grid-primary, #6750a4)}.sortable-header .sort-indicator .sort-tri-active.sort-tri-down{border-top-color:var(--grid-primary, #6750a4)}.sortable-header .sort-indicator .sort-priority{font-size:9px;font-weight:600;color:var(--grid-primary, #6750a4);line-height:1;min-width:12px;text-align:center}.sortable-header:hover .sort-indicator,.sortable-header.sort-asc .sort-indicator,.sortable-header.sort-desc .sort-indicator{opacity:1}.sortable-header:hover .sort-indicator .sort-tri:not(.sort-tri-active){opacity:.6}.sort-asc,.sort-desc{background-color:var(--grid-surface-container-low, rgba(103, 80, 164, .04))}.dragging{opacity:1;background-color:var(--grid-surface-container);box-shadow:var(--grid-elevation-2)}.drag-over{background-color:var(--grid-surface-container);border-color:var(--grid-primary)}.data-cell{background-color:transparent;color:var(--grid-on-surface);font-family:var(--grid-font-family);font-size:var(--grid-font-size-body);font-feature-settings:var(--grid-font-feature-numeric);padding:var(--grid-cell-padding-y) var(--grid-cell-padding-x)}.cell-content{align-items:center}.cell-content .mdc-text-field{padding:0px var(--grid-spacing-xxs)!important}.cell-display-text{align-items:center;padding:0px var(--grid-spacing-xs)}.ghost-loading-row{background-color:transparent}.ghost-cell-container{padding:var(--grid-spacing-sm)}.ghost-cell{height:20px;width:100%;background-color:var(--grid-surface-container);animation:pulse 1.5s ease-in-out infinite;border-radius:var(--grid-border-radius)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.column-resizer{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;background-color:transparent;transition:background-color .2s ease}.column-resizer:hover{background-color:var(--grid-primary)}.group-separator{height:var(--grid-spacing-sm);background-color:var(--grid-surface-variant)}.group-separator .separator-cell{background-color:var(--grid-surface-variant);border:none;height:var(--grid-spacing-sm)}.error-state{background-color:var(--grid-error-container);color:var(--grid-error);border-color:var(--grid-error)}.error-message{background-color:var(--grid-error);color:#fff;padding:var(--grid-spacing-sm);border-radius:var(--grid-border-radius);font-size:var(--grid-font-size-caption)}.incremental-row-container .eru-grid-table tbody,.incremental-row-container .eru-grid-table{position:relative}.incremental-row-container .eru-grid-table.show-column-lines{border-right:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-top:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-column-lines:not(.freeze-header){border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table:not(.show-column-lines){border:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table thead:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:calc(var(--grid-divider-width, 1px) * 2);background-color:var(--grid-divider-color, var(--grid-outline, #e0e0e0));pointer-events:none;z-index:10}.incremental-row-container .eru-grid-table.show-column-lines thead th,.incremental-row-container .eru-grid-table.show-column-lines tbody td{border-left:var(--grid-divider-width, 1px) solid var(--grid-divider-color, var(--grid-outline, #e0e0e0))!important}.incremental-row-container .eru-grid-table.show-row-lines thead th,.incremental-row-container .eru-grid-table.show-row-lines tbody td{border-bottom:var(--grid-divider-width, 1px) solid var(--grid-divider-color, var(--grid-outline, #e0e0e0))!important}@media(max-width:768px){.incremental-row-container{height:600px}.eru-grid-table th,.eru-grid-table td{font-size:var(--grid-font-size-caption)}.checkbox-column{width:40px;min-width:40px;max-width:40px}}@media(prefers-contrast:high){.eru-grid-table th,.eru-grid-table td{border-width:2px}.row-item:hover{border-width:2px;border-color:var(--grid-primary)}}@media(prefers-reduced-motion:reduce){.row-item,.column-drag-handle,.ghost-cell{transition:none;animation:none}}.pivot-table .nested-header{text-align:center;font-weight:600;background:var(--grid-surface-container)}.pivot-table .nested-header.row-dimension-header{background:var(--grid-surface-container);font-weight:600}.pivot-table .pivot-header-leafcols{padding:0;margin:0;height:0}.pivot-table .pivot-header-level.level-0 .nested-header{font-size:14px;padding:12px 8px}.pivot-table .pivot-header-level.level-1 .nested-header{font-size:13px;padding:10px 6px}.pivot-table .pivot-header-level.level-2 .nested-header{font-size:12px;padding:8px 4px}.pivot-table .nested-header:hover{background:var(--grid-surface-variant);color:var(--grid-primary);transition:all .2s ease}.pivot-table .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-table .pivot-cell-content{display:flex;justify-content:center;align-items:center;min-height:38px}.pivot-table .pivot-repeated-value .cell-content,.pivot-table .pivot-repeated-value .pivot-cell-content{visibility:hidden}.pivot-table .pivot-group-start.row-dimension-cell{border-top:1px solid var(--grid-outline, #79757f)}.pivot-mode .incremental-row-container{display:flex;flex-direction:column;height:auto;max-height:85vh;overflow:auto}.pivot-mode .h-shell{position:relative;width:calc(100% - var(--scrollbar-width, 17px))!important;top:0;z-index:1;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .h-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell{position:relative;bottom:50px;flex-shrink:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .gt-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell table{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.pivot-mode .gt-shell.adjust-bottom-vs{bottom:66px!important}.pivot-mode .gt-shell.adjust-bottom:not(.adjust-bottom-vs){bottom:calc(66px - var(--scrollbar-width, 17px))!important}.pivot-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .header-shell::-webkit-scrollbar{display:none}.pivot-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.pivot-mode .header-shell .eru-grid-table{margin-bottom:0;width:100%;table-layout:fixed}.pivot-mode .header-shell .eru-grid-table thead{background:var(--grid-surface-container)}.pivot-mode .header-shell .eru-grid-table thead th{background:var(--grid-surface-container);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .header-shell .eru-grid-table thead th.sticky-column{position:sticky;background:var(--grid-surface-container);z-index:111}.pivot-mode .header-shell .eru-grid-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-container{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.pivot-mode .pivot-table{width:auto!important;min-width:100%!important;table-layout:fixed!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important}.pivot-mode .pivot-table td,.pivot-mode .pivot-table th{box-sizing:border-box!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-table{table-layout:fixed!important;width:100%!important}.pivot-mode .pivot-table *{max-width:var(--col-width)!important;box-sizing:border-box!important}.pivot-mode .pivot-table colgroup{width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex-basis:var(--col-width)!important;flex:0 0 var(--col-width)!important}.pivot-mode .pivot-table table{width:100%!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important}.pivot-mode .pivot-table[style*=--table-total-width]{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:0 0 var(--col-width)!important;flex-basis:var(--col-width)!important;flex-grow:0!important;flex-shrink:0!important;overflow:hidden!important}.pivot-mode .pivot-table tbody td,.pivot-mode .pivot-table thead th{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.pivot-mode .pivot-table .cell-content,.pivot-mode .pivot-table data-cell{width:100%!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;display:block!important}.pivot-mode .pivot-table table{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-tbody tr.pivot-row{min-height:var(--grid-data-row-height, 50px)!important;height:var(--grid-data-row-height, 50px)!important}.pivot-mode .pivot-tbody tr.pivot-row:hover{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-tbody tr.pivot-row:nth-child(2n){background-color:#00000005}.pivot-mode .pivot-tbody tr.pivot-row td{min-height:var(--grid-data-row-height, 50px)!important;height:var(--grid-data-row-height, 50px)!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content{min-height:calc(var(--grid-data-row-height, 50px) - 2px);display:flex;align-items:center;justify-content:center}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content data-cell{width:100%;min-height:calc(var(--grid-data-row-height, 50px) - 4px);display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.pivot-mode .pivot-cell{vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-mode .pivot-cell .cell-content{display:flex;justify-content:center;align-items:center;min-height:var(--grid-header-row-height, 40px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}.pivot-mode .pivot-table .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.pivot-mode .pivot-table .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .subtotal-row td:first-child{color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row td.aggregated-value{font-weight:500;color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.pivot-mode .pivot-table .subtotal-bold td{font-weight:600!important;font-style:normal!important}.pivot-mode .pivot-table .subtotal-bold td.aggregated-value{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td{font-style:italic!important}.pivot-mode .pivot-table .subtotal-italic td:first-child{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.pivot-mode .pivot-table .subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted td.aggregated-value{font-weight:500!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted:hover,.pivot-mode .pivot-table .subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-row{background-color:var(--grid-surface-container-high)!important;font-weight:700;font-size:var(--grid-font-size-body)}.pivot-mode .pivot-table .grand-total-row td{background-color:var(--grid-surface-container-high)!important;color:var(--grid-on-surface)}.pivot-mode .pivot-table .grand-total-row td:first-child{font-style:normal;font-weight:800;color:var(--grid-primary)}.pivot-mode .pivot-table .grand-total-row td.aggregated-value{font-weight:500;color:var(--grid-primary);font-family:Roboto Mono,monospace}.pivot-mode .pivot-table .grand-total-row:hover,.pivot-mode .pivot-table .grand-total-row:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-bold td{font-weight:700!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-bold td.aggregated-value{font-weight:700!important}.pivot-mode .pivot-table .grand-total-italic td,.pivot-mode .pivot-table .grand-total-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted{background-color:var(--grid-primary)!important;box-shadow:var(--grid-elevation-2)!important}.pivot-mode .pivot-table .grand-total-highlighted td{background-color:var(--grid-primary)!important;color:var(--grid-on-primary)!important;font-weight:500!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-highlighted td.aggregated-value{color:var(--grid-on-primary)!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted:hover,.pivot-mode .pivot-table .grand-total-highlighted:hover td{background-color:var(--grid-primary)!important}.pivot-mode .pivot-table .collapsible-header{position:relative}.pivot-mode .pivot-table .collapsible-header .header-content{display:flex;align-items:center;justify-content:space-between;gap:var(--grid-spacing-xs);padding:var(--grid-spacing-xs) var(--grid-spacing-sm)}.pivot-mode .pivot-table .collapsible-header .header-label{flex:1;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn{background:none;border:none;cursor:pointer;padding:var(--grid-spacing-xxs);margin:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--grid-border-radius);color:var(--grid-on-surface-variant);transition:all .2s ease;font-size:12px;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:hover{background-color:var(--grid-surface-container);color:var(--grid-primary);transform:scale(1.1)}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:focus{outline:2px solid var(--grid-primary);outline-offset:1px}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn .collapse-icon{display:block;line-height:1;font-family:monospace;font-size:14px}.pivot-mode .pivot-table .collapsible-header.expanded .collapse-toggle-btn .collapse-icon{color:var(--grid-primary)}.pivot-mode .pivot-table .collapsible-header.collapsed{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .header-label{font-style:italic;color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .collapse-toggle-btn .collapse-icon{color:var(--grid-outline)}.pivot-mode .pivot-table .collapsible-header:hover{background-color:var(--grid-surface-container)}.pivot-mode .pivot-table .collapsible-header:hover .header-label{color:var(--grid-on-surface)}.pivot-mode .pivot-table .pivot-single-table{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden;min-height:var(--table-min-height)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container{flex-shrink:0;background:var(--grid-surface)!important;overflow-x:auto;overflow-y:hidden;min-height:100px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table{width:auto;min-width:100%;height:auto!important;min-height:100px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th{background:var(--grid-surface-container)!important;padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:40px!important;height:auto!important;position:relative;visibility:visible!important;color:var(--grid-on-surface)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:101!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container{flex:1;overflow:auto;min-height:300px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-viewport{height:100%!important;width:100%!important;overflow-x:auto!important;overflow-y:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table{width:auto;min-width:100%;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td{padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:32px!important;height:auto!important;background:var(--grid-surface)!important;color:var(--grid-on-surface)!important;visibility:visible!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td.sticky-column,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:100!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr{height:auto!important;min-height:50px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr.pivot-row,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr.pivot-row{visibility:visible!important;display:table-row!important}.pivot-mode .pivot-table .collapsed-column-group{background-color:var(--grid-surface-container);border-left:3px solid var(--grid-primary)}.pivot-mode .pivot-table .collapsed-column-group:hover{background-color:var(--grid-surface-container-high)}.pivot-row.subtotal-row{background-color:var(--grid-surface-variant);font-weight:500}.pivot-row.subtotal-row.subtotal-bold{font-weight:500}.pivot-row.subtotal-row.subtotal-italic{font-style:italic}.pivot-row.subtotal-row.subtotal-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.grand-total-row{background-color:var(--grid-surface-container);font-weight:600}.pivot-row.grand-total-row.grand-total-bold{font-weight:800}.pivot-row.grand-total-row.grand-total-italic{font-style:italic}.pivot-row.grand-total-row.grand-total-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.first-visible-row{background-color:#6750a41a!important;position:relative}.pivot-row.first-visible-row:before{content:\"\\1f441\\fe0f First Visible\";position:absolute;top:-20px;left:0;background:var(--grid-primary);color:var(--grid-on-primary);padding:2px 6px;font-size:10px;border-radius:2px;z-index:1000}.header-wrap-text{white-space:pre-wrap;word-break:auto-phrase}.group-header-row{display:flex;align-items:center;justify-content:space-between;width:100%;padding-right:12px}.custom-collapse-header{background-color:var(--grid-surface-variant);padding:8px 20px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:pointer;display:flex;width:fit-content;align-items:center;-webkit-user-select:none;user-select:none;min-width:200px;margin-bottom:10px;position:sticky;left:1px;z-index:116}.custom-collapse-header .collapse-arrow{display:inline-block;margin-right:8px;font-size:12px;color:var(--grid-on-surface-variant);transition:transform .2s ease;transform:rotate(0)}.custom-collapse-header .collapse-arrow.rotate-arrow{transform:rotate(270deg)}.custom-collapse-header .f-12{font-size:12px;color:var(--grid-on-surface)}.custom-collapse-header .group-sort-indicator{display:inline-flex;align-items:center;margin-left:8px}.custom-collapse-header .group-sort-indicator .sort-triangles{display:flex;flex-direction:column;align-items:center;gap:2px}.custom-collapse-header .group-sort-indicator .sort-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;cursor:pointer;transition:border-color .15s ease}.custom-collapse-header .group-sort-indicator .sort-tri-up{border-bottom:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.custom-collapse-header .group-sort-indicator .sort-tri-down{border-top:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.custom-collapse-header .group-sort-indicator .sort-tri-active{opacity:1}.custom-collapse-header .group-sort-indicator .sort-tri-active.sort-tri-up{border-bottom-color:var(--grid-primary, #6750a4)}.custom-collapse-header .group-sort-indicator .sort-tri-active.sort-tri-down{border-top-color:var(--grid-primary, #6750a4)}.excel-download-icon{cursor:pointer}.excel-download-icon:hover{opacity:.75}.excel-download-bar{display:flex;justify-content:flex-end;padding:4px 12px}.table-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.table-mode .header-shell::-webkit-scrollbar{display:none}.table-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.table-mode .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.table-mode .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.table-mode .subtotal-row td:first-child{color:var(--grid-primary)}.table-mode .subtotal-row td.subtotal-cell{font-weight:500}.table-mode .subtotal-row td.subtotal-cell .subtotal-label{font-weight:600;color:var(--grid-primary)}.table-mode .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.table-mode .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.table-mode .subtotal-row.subtotal-bold td{font-weight:600!important;font-style:normal!important}.table-mode .subtotal-row.subtotal-italic td{font-style:italic!important}.table-mode .subtotal-row.subtotal-italic td:first-child{font-weight:600!important}.table-mode .subtotal-row.subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.table-mode .subtotal-row.subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.table-mode .subtotal-row.subtotal-highlighted:hover,.table-mode .subtotal-row.subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.table-mode .subtotal-row-shell{width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.table-mode .subtotal-row-shell::-webkit-scrollbar{display:none}.board-mode-host{overflow:hidden;display:flex;flex-direction:column;height:var(--grid-height, 600px)}.board-mode-host .board-view-container{display:flex;flex-direction:column;flex:1;min-height:0}.board-mode-host .board-sort-bar{display:flex;align-items:center;gap:6px;padding:8px 16px;flex-shrink:0;border-bottom:1px solid var(--grid-outline-variant, #cac4d0);background:var(--grid-surface, #fffbfe);overflow-x:auto}.board-mode-host .board-sort-bar .board-sort-label{font-size:12px;font-weight:500;color:var(--grid-on-surface-variant, #49454f);white-space:nowrap}.board-mode-host .board-sort-bar .board-sort-chip{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:16px;border:1px solid var(--grid-outline-variant, #cac4d0);background:var(--grid-surface, #fffbfe);color:var(--grid-on-surface, #1d1b20);font-size:12px;white-space:nowrap}.board-mode-host .board-sort-bar .board-sort-chip-active{background:var(--grid-surface-container);border-color:var(--grid-outline, #79757f);color:var(--grid-on-surface, #1d1b20)}.board-mode-host .board-sort-bar .board-sort-chip-label{pointer-events:none}.board-mode-host .board-sort-bar .board-sort-chip-arrow{font-size:10px;line-height:1;cursor:pointer;padding:2px;border-radius:4px}.board-mode-host .board-sort-bar .board-sort-chip-arrow:hover{background:#00000014}.board-mode-host .board-sort-bar .board-sort-chip-priority{font-size:9px;font-weight:700;background:var(--grid-primary, #6750a4);color:var(--grid-on-primary, #ffffff);border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center}.board-mode-host .board-sort-bar .board-sort-chip-remove{font-size:10px;cursor:pointer;padding:2px;border-radius:4px;color:var(--grid-on-surface-variant, #49454f)}.board-mode-host .board-sort-bar .board-sort-chip-remove:hover{background:#00000014;color:var(--grid-error, #b3261e)}.board-mode-host .board-sort-bar .board-sort-add-btn{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:16px;border:1px dashed var(--grid-outline-variant, #cac4d0);background:transparent;color:var(--grid-on-surface-variant, #49454f);font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s ease,border-color .15s ease}.board-mode-host .board-sort-bar .board-sort-add-btn .board-sort-add-icon{font-size:14px;width:14px;height:14px}.board-mode-host .board-sort-bar .board-sort-add-btn:hover{background:var(--grid-surface-container-low, #f7f2fa);border-color:var(--grid-primary, #6750a4);color:var(--grid-primary, #6750a4)}.board-mode-host .board-sort-bar .board-sort-clear{display:inline-flex;align-items:center;padding:4px 10px;border-radius:16px;border:1px solid var(--grid-error, #b3261e);background:transparent;color:var(--grid-error, #b3261e);font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s ease}.board-mode-host .board-sort-bar .board-sort-clear:hover{background:#b3261e14}.board-mode-host .board-columns-wrapper{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--board-col-min-width, 300px),var(--board-col-max-width, 1fr)));grid-auto-rows:var(--board-column-height, 420px);gap:16px;flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;align-content:start;justify-content:start}.board-mode-host .board-columns-wrapper.board-columns-nowrap{grid-auto-flow:column;grid-template-columns:none;grid-template-rows:var(--board-column-height, 420px);grid-auto-rows:auto;grid-auto-columns:minmax(var(--board-col-min-width, 300px),var(--board-col-max-width, 1fr));overflow-x:auto;overflow-y:hidden}.board-mode-host .board-column{height:var(--board-column-height, 420px);min-width:0;display:flex;flex-direction:column;background:var(--grid-surface-container, #f3edf7);border-radius:12px;min-height:0;overflow:hidden}.board-mode-host .board-column.board-column-accented{border-top:3px solid var(--board-group-color, transparent)}.board-mode-host .board-column .column-header{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;font-weight:600;flex-shrink:0}.board-mode-host .board-column .column-header:hover{background-color:transparent}.board-mode-host .board-column .column-header .column-header-title{font-size:15px;font-weight:700;letter-spacing:.2px;line-height:1.2;color:var(--grid-on-surface, #1d1b20);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.board-mode-host .board-column .column-header .column-header-title-cell{display:inline-flex;align-items:center;flex:1 1 auto;min-width:0;overflow:visible;text-overflow:clip}.board-mode-host .board-column .column-header .column-header-title-cell data-cell,.board-mode-host .board-column .column-header .column-header-title-cell .data-cell-component,.board-mode-host .board-column .column-header .column-header-title-cell .container{padding:0!important;margin:0!important;border:none!important;background:transparent!important;min-height:0!important;height:auto!important;width:auto!important;max-width:100%!important;overflow:visible!important}.board-mode-host .board-column .column-header .column-header-title-cell .status-display,.board-mode-host .board-column .column-header .column-header-title-cell .status-display-content,.board-mode-host .board-column .column-header .column-header-title-cell .status-text,.board-mode-host .board-column .column-header .column-header-title-cell .tag-display,.board-mode-host .board-column .column-header .column-header-title-cell .tag-text{max-width:none!important;overflow:visible!important;text-overflow:clip!important}.board-mode-host .board-column .column-header .column-header-count{font-size:10px;font-weight:600;color:var(--grid-on-surface-variant, #49454f);background:var(--grid-surface-variant, #e7e0ec);border-radius:10px;padding:3px 10px;white-space:nowrap;flex-shrink:0}.board-mode-host .board-column-body{flex:1;min-height:0;height:0}.board-mode-host .board-card-container{box-sizing:border-box;overflow:hidden;border-radius:8px;transition:background-color .15s ease,box-shadow .15s ease}.board-mode-host .board-card-container.show-row-lines{box-shadow:inset 0 0 0 var(--grid-divider-width, 1px) var(--grid-divider-color, var(--grid-outline, #e0e0e0))}.board-mode-host .board-card-container:hover{background-color:var(--eru-board-card-hover-bg, color-mix(in srgb, var(--mat-sys-primary, #1976d2) 8%, transparent))}.board-mode-host .board-card-container.selected{background-color:var(--eru-board-card-selected-bg, color-mix(in srgb, var(--mat-sys-primary, #1976d2) 14%, transparent));box-shadow:inset 0 0 0 2px var(--eru-board-card-selected-outline, var(--mat-sys-primary, #1976d2))}.board-mode-host .board-card{height:calc(100% - 8px);overflow:hidden;cursor:pointer}.board-mode-host .board-card mat-card-title{font-size:13px}.board-mode-host .board-card mat-card-subtitle{font-size:12px}.board-mode-host .board-card-field{display:flex;flex-direction:column;margin-bottom:4px}.board-mode-host .board-field-label{font-size:10px;color:var(--grid-on-surface-variant, #49454f);font-weight:500;text-transform:uppercase;letter-spacing:.5px}.board-mode-host .board-ghost-card{margin:8px;padding:16px;background:var(--grid-surface, #fef7ff);border-radius:8px;animation:board-pulse 1.5s ease-in-out infinite}.board-mode-host .board-ghost-line{height:12px;background:var(--grid-surface-variant, #e7e0ec);border-radius:4px;margin-bottom:8px}.board-mode-host .board-ghost-line--short{width:60%}@keyframes board-pulse{0%,to{opacity:1}50%{opacity:.5}}th.row-expand-toggle,td.row-expand-toggle{width:40px!important;min-width:40px!important;max-width:40px!important;padding:0!important;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;user-select:none;box-sizing:border-box}.row-expand-icon{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--grid-on-surface-variant);transition:transform .15s ease-in-out}.row-expand-icon.expanded{transform:rotate(90deg)}.row-detail{background:var(--grid-surface-container)}.row-detail .row-detail-cell{padding:var(--grid-spacing-sm) var(--grid-spacing-md);border-bottom:1px solid var(--grid-outline-variant)}.row-detail .row-detail-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--grid-spacing-sm) var(--grid-spacing-md)}.row-detail .row-detail-field{display:flex;flex-direction:column;gap:var(--grid-spacing-xxs);min-width:0}.row-detail .row-detail-label{font-size:var(--grid-font-size-caption);color:var(--grid-on-surface-variant);font-weight:500}.row-detail .row-detail-value{min-width:0}.row-detail .row-detail-value data-cell{display:block;width:100%}\n"], dependencies: [{ kind: "component", type: DataCellComponent, selector: "data-cell", inputs: ["eruGridStore", "fieldSize", "columnDatatype", "columnName", "column", "value", "id", "frozenGrandTotalCell", "td", "drillable", "mode", "isEditable", "row", "personCardTemplate"], outputs: ["tdChange"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1$3.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1$3.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1$3.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i5.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i5.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i5.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i7.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: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuContent, selector: "ng-template[matMenuContent]" }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: ResizeColumnDirective, selector: "[resizeColumn]", inputs: ["resizeColumn", "index", "columnConfig", "gridConfig"] }, { kind: "directive", type: ColumnDragDirective, selector: "[columnDraggable]", inputs: ["columnDraggable"] }, { kind: "component", type: ColumnDesignPanelComponent, selector: "eru-column-design-panel" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
14624
|
+
], viewQueries: [{ propertyName: "rowContainer", first: true, predicate: ["rowContainer"], descendants: true }, { propertyName: "headerScroller", first: true, predicate: ["headerScroller"], descendants: true, read: ElementRef }, { propertyName: "gtScroller", first: true, predicate: ["gtScroller"], descendants: true, read: ElementRef }, { propertyName: "viewport", first: true, predicate: ["vp"], descendants: true }, { propertyName: "groupsViewport", first: true, predicate: ["groupsViewport"], descendants: true }, { propertyName: "groupsScrollContainerEl", first: true, predicate: ["groupsScrollContainer"], descendants: true }, { propertyName: "allViewports", predicate: CdkVirtualScrollViewport, descendants: true }, { propertyName: "headerScrollers", predicate: ["headerScroller"], descendants: true }], ngImport: i0, template: "<!-- <div style=\"background: #f0f0f0; font-size: 12px; border-bottom: 1px solid #ccc;\">\ncurrentPivotScrollIndex {{currentPivotScrollIndex()}} |\nfirstDataRowIndex {{firstDataRowIndex()}} |\nfirstTr {{firstTr}} |\nmaxDepth {{maxDepth()}}\n</div> -->\n<div class=\"incremental-row-container eru-grid\" #rowContainer [class.pivot-mode]=\"gridStore.isPivotMode()\"\n [class.table-mode]=\"!gridStore.isPivotMode() && !isBoardMode()\" [class.board-mode-host]=\"isBoardMode()\">\n <eru-column-design-panel></eru-column-design-panel>\n <!-- Pivot Mode Template -->\n @if (gridStore.isPivotMode()) {\n <ng-container>\n <div class=\"pivot-container\" style=\"display: flex; flex-direction: column; height: 100%;\"\n [style]=\"'--table-min-height: ' + getInitialMinHeightPx() + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <!-- Debug info for first visible row -->\n\n\n <div class=\"pivot-single-table\"\n style=\"height: 100%; width: 100%; overflow: hidden; display: flex; flex-direction: column;\">\n @if (freezeHeader()) {\n <div #headerScroller class=\"header-shell\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n @if(grandTotalPosition() === 'before' && freezeGrandTotal()) {\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n }\n </table>\n </div>\n }\n <!-- Virtual Scrolled Table Body -->\n <div>\n <cdk-virtual-scroll-viewport #vp [itemSize]=\"dataRowHeight()\" class=\"viewport pivot-viewport\"\n [class.apply-cdk-width]=\"applyCdkWidth()\" (scrolledIndexChange)=\"onPivotScroll($event)\"\n (scroll)=\"onBodyScroll($event)\" style=\"overflow: auto;\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n @if (!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n }\n <!-- Table Body with Virtual Scrolling -->\n <tbody class=\"pivot-tbody\">\n\n <tr *cdkVirtualFor=\"let pivotRow of gridStore.pivotDisplayData(); \n trackBy: trackByPivotRowFn; \n let i = index\" class=\"pivot-row\" [class.subtotal-row]=\"pivotRow._isSubtotal\"\n [class.grand-total-row]=\"pivotRow._isGrandTotal\"\n [class.subtotal-bold]=\"pivotRow._isSubtotal && subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"pivotRow._isSubtotal && subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"pivotRow._isSubtotal && subTotalStyle() === 'highlighted'\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\" [style.cursor]=\"cursorOnHover() || null\" [attr.data-pivot-row]=\"i\">\n @if ((!pivotRow._isGrandTotal && freezeGrandTotal() ) || (!freezeGrandTotal() )) {\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.pivot-repeated-value]=\"isRepeatedDimensionValue(i, column.name)\"\n [class.pivot-group-start]=\"isPivotGroupStart(i, column.name)\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content pivot-cell-content\">\n <data-cell [personCardTemplate]=\"personCardTemplate\" [class.aggregation]=\"!!column.aggregationFunction\" [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\" [value]=\"pivotRow[column.name]\"\n [column]=\"column\" [drillable]=\"column.enableDrilldown || false\" [mode]=\"mode()\"\n [isEditable]=\"isEditable()\" [id]=\"'pivot_' + i + '_' + column.name\" [eruGridStore]=\"gridStore\"\n [row]=\"pivotRow\">\n </data-cell>\n </div>\n </td>\n }\n } @else {\n <td [style.height.px]=\"dataRowHeight()\" [attr.colspan]=\"getLeafColumns().length\"> </td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n </div>\n @if (freezeGrandTotal() && grandTotalPosition() === 'after') {\n <div #gtScroller class=\"header-shell gt-shell\" [class.adjust-bottom]=\"!applyCdkWidth()\"\n [class.adjust-bottom-vs]=\"adjustScrollWidth()\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n\n </table>\n </div>\n }\n\n\n </div>\n </div>\n </ng-container>\n } @else if (isBoardMode()) {\n <!-- Board Mode Template -->\n <div class=\"board-view-container\">\n @if(showSortBar()) {\n <div class=\"board-sort-bar\">\n <span class=\"board-sort-label\">Sort by:</span>\n @for (entry of gridStore.sortColumns(); track getFieldName(entry)) {\n <span class=\"board-sort-chip board-sort-chip-active\">\n <span class=\"board-sort-chip-label\">{{getColumnLabel(entry)}}</span>\n <span class=\"board-sort-chip-arrow\" (click)=\"onBoardSortChipToggle($event, entry)\">\n @if(!entry.startsWith('-')) { \u25B2 } @else { \u25BC }\n </span>\n @if(gridStore.sortColumns().length > 1) {\n <span class=\"board-sort-chip-priority\">{{getSortPriority(getFieldName(entry))}}</span>\n }\n <span class=\"board-sort-chip-remove\" (click)=\"onBoardSortChipRemove($event, entry)\">\u2715</span>\n </span>\n }\n <button class=\"board-sort-add-btn\" [matMenuTriggerFor]=\"sortFieldMenu\">\n <mat-icon class=\"board-sort-add-icon\">add</mat-icon> Add field\n </button>\n <mat-menu #sortFieldMenu=\"matMenu\" class=\"board-sort-menu\">\n @for (column of columns(); track column.name) {\n <button mat-menu-item (click)=\"onBoardSortFieldSelect(column)\"\n [disabled]=\"getSortDirection(column.name) !== null\">\n @if(getSortDirection(column.name) !== null) {\n <mat-icon>check</mat-icon>\n } @else {\n <mat-icon></mat-icon>\n }\n {{column.label}}\n </button>\n }\n </mat-menu>\n @if(gridStore.sortColumns().length > 0) {\n <button class=\"board-sort-clear\" (click)=\"onBoardSortClear()\">\u2715 Clear</button>\n }\n </div>\n }\n <div class=\"board-columns-wrapper\" [class.board-columns-nowrap]=\"!boardWrapColumns()\">\n @for (group of groups(); track group.id) {\n <div class=\"board-column\" [class.board-column-accented]=\"!!boardGroupColor(group)\"\n [style.--board-group-color]=\"boardGroupColor(group)\">\n @if (showBoardColumnHeader()) {\n <div class=\"column-header\">\n <!-- Render the group value through the same read-only cell renderer a\n data cell uses, so the grouped field's datatype formats itself\n (status/tag pills, dates, numbers) instead of printing raw text. -->\n @if (groupByColumn(); as gcol) {\n <span class=\"column-header-title column-header-title-cell\">\n <data-cell\n [eruGridStore]=\"gridStore\"\n [column]=\"gcol\"\n [columnDatatype]=\"gcol.datatype\"\n [columnName]=\"gcol.name\"\n [value]=\"group.title\"\n [id]=\"'board-group-' + group.id\"\n [fieldSize]=\"0\"\n [isEditable]=\"false\"\n [mode]=\"'board-group-header'\">\n </data-cell>\n </span>\n } @else {\n <span class=\"column-header-title\">{{ group.title }}</span>\n }\n <span class=\"column-header-count\">{{ group.currentLoadedRows || 0 }} of {{ group.totalRowCount || 0 }}</span>\n </div>\n }\n <cdk-virtual-scroll-viewport [attr.data-group-id]=\"group.id\" [itemSize]=\"boardCardSlot\" class=\"board-column-body\"\n [style.height.px]=\"boardColumnBodyHeight(group)\"\n (scrolledIndexChange)=\"onBoardScrolledIndexChange($event, group)\">\n <div\n *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id)(); templateCacheSize: 0\"\n class=\"board-card-container\"\n [class.selected]=\"isBoardCardActive(row)\"\n [class.show-row-lines]=\"showRowLines()\"\n [style.height.px]=\"boardCardOuterHeight\"\n [style.padding.px]=\"boardCardPadding\"\n [style.marginBottom.px]=\"boardCardGap\"\n [style.cursor]=\"cursorOnHover() || null\"\n (click)=\"emitRowSelect(row, 'board', group)\">\n <!-- Custom template when consumer provides boardCardTemplate; default card otherwise -->\n <ng-container\n *ngTemplateOutlet=\"boardCardTemplate ?? defaultBoardCard;\n context: { $implicit: row, columns: visibleBoardFields(), group: group }\">\n </ng-container>\n </div>\n </cdk-virtual-scroll-viewport>\n @if (group.isLoading) {\n <div class=\"board-ghost-card\">\n <div class=\"board-ghost-line\"></div>\n <div class=\"board-ghost-line board-ghost-line--short\"></div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else {\n\n <!-- Table Mode Template -->\n <ng-template #excelDownloadIcon>\n <svg class=\"excel-download-icon\" title=\"Download Excel\" (click)=\"onExcelDownloadClick($event)\"\n xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" width=\"24px\" height=\"24px\">\n <path fill=\"#169154\" d=\"M29,6H15.744C14.781,6,14,6.781,14,7.744v7.259h15V6z\" />\n <path fill=\"#18482a\" d=\"M14,33.054v7.202C14,41.219,14.781,42,15.743,42H29v-8.946H14z\" />\n <path fill=\"#0c8045\" d=\"M14 15.003H29V24.005000000000003H14z\" />\n <path fill=\"#17472a\" d=\"M14 24.005H29V33.055H14z\" />\n <g>\n <path fill=\"#29c27f\" d=\"M42.256,6H29v9.003h15V7.744C44,6.781,43.219,6,42.256,6z\" />\n <path fill=\"#27663f\" d=\"M29,33.054V42h13.257C43.219,42,44,41.219,44,40.257v-7.202H29z\" />\n <path fill=\"#19ac65\" d=\"M29 15.003H44V24.005000000000003H29z\" />\n <path fill=\"#129652\" d=\"M29 24.005H44V33.055H29z\" />\n </g>\n <path fill=\"#0c7238\"\n d=\"M22.319,34H5.681C4.753,34,4,33.247,4,32.319V15.681C4,14.753,4.753,14,5.681,14h16.638 C23.247,14,24,14.753,24,15.681v16.638C24,33.247,23.247,34,22.319,34z\" />\n <path fill=\"#fff\"\n d=\"M9.807 19L12.193 19 14.129 22.754 16.175 19 18.404 19 15.333 24 18.474 29 16.123 29 14.013 25.07 11.912 29 9.526 29 12.719 23.982z\" />\n </svg>\n </ng-template>\n @if(showExcelDownload() && !showGroupBar()) {\n <div class=\"excel-download-bar\">\n <ng-container *ngTemplateOutlet=\"excelDownloadIcon\"></ng-container>\n </div>\n }\n <!-- Scrollable groups container \u2014 plain iteration avoids CDK fixed-height estimation errors -->\n <div #groupsScrollContainer class=\"groups-scroll-container\" (scroll)=\"onGroupsViewportScroll($event)\">\n\n @for (group of groups(); track trackByGroupFn($index, group); let i = $index) {\n <div class=\"group-container\"\n [attr.data-group-id]=\"group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id\">\n <!-- Combined sticky header with group info and table -->\n <div style=\"\n background:var(--grid-surface);\n position: sticky;\n top: 0;\n z-index: 115;\n \">\n @if(showGroupBar()) {\n <div class=\"group-header-row\">\n <div class=\"custom-collapse-header\" (click)=\"toggleGroupCollapse(group.id)\">\n <span class=\"collapse-arrow\" [ngClass]=\"{\n 'rotate-arrow': group.isExpanded,\n }\">\u25BC</span>\n <span class=\"f-12\">\n {{ group?.title || \"\" }}\n {{ group?.currentLoadedRows || 0 }} -\n {{ group?.totalRowCount || 0 }} rows...</span>\n @if(groupByField() && isSortable()) {\n <span class=\"group-sort-indicator\">\n <span class=\"sort-triangles\">\n <span class=\"sort-tri sort-tri-up\" [class.sort-tri-active]=\"getSortDirection(groupByField()!) === 'asc'\"\n (click)=\"onGroupSortToggle($event, 'asc')\"></span>\n <span class=\"sort-tri sort-tri-down\"\n [class.sort-tri-active]=\"getSortDirection(groupByField()!) === 'desc'\"\n (click)=\"onGroupSortToggle($event, 'desc')\"></span>\n </span>\n </span>\n }\n </div>\n @if(i === 0 && showExcelDownload()) {\n <ng-container *ngTemplateOutlet=\"excelDownloadIcon\"></ng-container>\n }\n </div>\n }\n\n @if(freezeHeader() && (group.isExpanded || !showGroupBar())) {\n <div #headerScroller class=\"header-shell\" [attr.data-group-id]=\"'header-shell-' + group.id\"\n [style]=\"'--table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <table class=\"eru-grid-table\" [class.freeze-header]=\"freezeHeader()\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"tableColGroup\"></ng-container>\n <ng-container *ngTemplateOutlet=\"tableHeader\"></ng-container>\n <!-- Grand Total row after sticky header (position: before) - only for first group -->\n @if(enableColumnGrandTotal() && grandTotalPositionColumn() === 'before' && hasGrandTotalData() && i === 0) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n </tbody>\n }\n <!-- Subtotal row after sticky header (position: before) -->\n @if(enableColumnSubtotals() && subtotalPositionColumn() === 'before' && hasSubtotalData(group)) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n </tbody>\n }\n </table>\n </div>\n }\n </div>\n @if(group.isExpanded || !showGroupBar()) {\n <ng-container>\n <cdk-virtual-scroll-viewport [attr.data-group-id]=\"group.id\" [itemSize]=\"dataRowHeight()\" class=\"viewport table-viewport\"\n (scrolledIndexChange)=\"onScroll($event, group)\" (scroll)=\"onTableBodyScroll($event)\"\n [style]=\"'--table-height: ' + getGroupContentHeight(group.id) + 'px; --table-min-height: ' + getGroupContentHeight(group.id) + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <div class=\"table-wrapper\">\n <table class=\"eru-grid-table\" [class.show-column-lines]=\"showColumnLines()\"\n [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"tableColGroup\"></ng-container>\n @if(!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"tableHeader\"></ng-container>\n }\n <!-- Grand Total row after normal header (position: before) - only for first group -->\n @if(!freezeHeader() && enableColumnGrandTotal() && grandTotalPositionColumn() === 'before' &&\n hasGrandTotalData() && i === 0) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n </tbody>\n }\n <!-- Subtotal row after normal header (position: before) -->\n @if(!freezeHeader() && enableColumnSubtotals() && subtotalPositionColumn() === 'before' &&\n hasSubtotalData(group)) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n </tbody>\n }\n <tbody>\n @if (columns(); as columnsList) {\n <!-- <tr *ngIf=\"groupItem.type === 'table-header' && groups().length > 1\" style=\"background:#fafafa\">\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isGroupSelected(groupItem.group?.id || '')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleGroupSelection($event, groupItem.group?.id || '')\"\n >\n </th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn;let i =index\"\n style=\"text-align: center;\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"true\"\n [columnConfig]=\"column\"\n [columnDraggable]=\"i\"\n class=\"column-header\">\n <div class=\"column-drag-handle\"></div>\n {{column.label}} {{column.symbol}}\n </th>\n </tr> -->\n <!-- @if(getRowsForGroup(group.id).length > 0 && group.isExpanded) { -->\n <!-- *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id)(); \n trackBy: trackByRowFn; \n let i = index\" -->\n <!-- @for(row of getRowsForGroupSignal(group.id)(); track trackByRowFn($index, row); let i = $index) { -->\n <ng-container\n *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id)(); trackBy: trackByRowFn; let i = index\">\n <tr class=\"row-item\" [attr.data-row-id]=\"i\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\" [style.cursor]=\"cursorOnHover() || null\" (click)=\"emitRowSelect(row, 'table', group)\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\" style=\"text-align: center;\">\n <input type=\"checkbox\" [checked]=\"isRowSelected(row?.entity_id)\"\n (change)=\"toggleRowSelection($event, row)\">\n </td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <ng-container\n *ngTemplateOutlet=\"actionCell; context: { $implicit: row, mode: 'table', group: group }\"></ng-container>\n </td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\" (click)=\"toggleRowExpand(row, i, $event)\">\n <mat-icon class=\"row-expand-icon\" [class.expanded]=\"isRowExpanded(row, i)\">chevron_right</mat-icon>\n </td>\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <td #cell [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n class=\"data-cell\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\"\n [matTooltipClass]=\"'error-message'\" [matTooltip]=\"datacell.error()?'Error: ' + datacell.error():''\"\n matTooltipPosition=\"below\">\n <div class=\"cell-content\">\n <data-cell #datacell [personCardTemplate]=\"personCardTemplate\" [td]=cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\" [value]=\"(row?.['entity_data']?.[column.name] ?? row?.[column.name]) || ''\" [column]=\"column\"\n [mode]=\"mode()\" [isEditable]=\"isEditable() && column.editable !== false && column.editable !== 'false'\" [drillable]=\"column.enableDrilldown || false\"\n [id]=\"i + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"row\"></data-cell>\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <ng-container\n *ngTemplateOutlet=\"actionCell; context: { $implicit: row, mode: 'table', group: group }\"></ng-container>\n </td>\n }\n </tr>\n @if(hasHiddenColumns() && isRowExpanded(row, i)) {\n <tr class=\"row-detail\">\n <td class=\"row-detail-cell\" [attr.colspan]=\"rowDetailColspan()\">\n <div class=\"row-detail-grid\">\n @for (hiddenCol of hiddenColumns(); track trackByColumnFn($index, hiddenCol)) {\n <div class=\"row-detail-field\">\n <span class=\"row-detail-label\">{{hiddenCol.label}}</span>\n <div class=\"row-detail-value\">\n <data-cell [fieldSize]=\"hiddenCol.field_size\" [columnDatatype]=\"hiddenCol.datatype\"\n [columnName]=\"hiddenCol.name\" [value]=\"(row?.['entity_data']?.[hiddenCol.name] ?? row?.[hiddenCol.name]) || ''\"\n [column]=\"hiddenCol\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [drillable]=\"hiddenCol.enableDrilldown || false\"\n [id]=\"'detail_' + i + '_' + hiddenCol.name\" [eruGridStore]=\"gridStore\" [row]=\"row\"></data-cell>\n </div>\n </div>\n }\n </div>\n </td>\n </tr>\n }\n </ng-container>\n <!-- } -->\n <!-- } -->\n @if(group.isLoading && (group.isExpanded || !showGroupBar())) {\n @for(i of [].constructor(ghostRows()); let j = $index; track j) {\n <tr class=\"ghost-loading-row\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column ghost-cell-container\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n class=\"ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column ghost-cell-container\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n </tr>\n }\n }\n <!-- <tr\n *ngIf=\"getRowsForGroup(group.id).length === 0 && !group.isExpanded\"\n class=\"group-separator\"\n >\n <td [attr.colspan]=\"groupSeperatorColSpan()\" class=\"separator-cell\"></td>\n </tr> -->\n <!-- Subtotal row at end of group (position: after) -->\n @if(enableColumnSubtotals() && subtotalPositionColumn() === 'after' && hasSubtotalData(group)) {\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n }\n <!-- Grand Total row at end of group (position: after) - only for last group -->\n @if(enableColumnGrandTotal() && grandTotalPositionColumn() === 'after' && hasGrandTotalData() && i ===\n groups().length - 1) {\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n }\n }\n </tbody>\n </table>\n </div>\n </cdk-virtual-scroll-viewport>\n </ng-container>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Pivot Table Header Template -->\n<ng-template #pivotTableHead>\n <thead [class.eru-wrap-headers]=\"wrapHeaders()\">\n @if (hasNestedHeaders()) {\n <ng-container>\n @for (headerRow of getHeaderRows(); track headerRow; let rowIndex = $index) {\n <tr class=\"pivot-header pivot-header-container\" [class.pivot-header-level]=\"'level-' + rowIndex\">\n @for (header of headerRow; track trackByHeaderFn($index, header); let colIndex = $index) {\n <th [attr.colspan]=\"header.colspan\" [attr.rowspan]=\"header.rowspan\"\n [resizeColumn]=\"isResizablePivotHeader(header)\"\n [columnConfig]=\"getFieldForPivotHeader(header) || $any(header)\"\n class=\"column-header pivot-column-header nested-header\"\n [class.row-dimension-header]=\"isRowDimensionHeader(header)\"\n [class.column-dimension-header]=\"!isRowDimensionHeader(header)\" [class.expanded]=\"header.isExpanded\"\n [class.collapsed]=\"!header.isExpanded\" [class.sticky-column]=\"isStickyColumn(header.name, colIndex)\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === designTargetFor($any(header))\"\n [style.position]=\"isStickyColumn(header.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(header.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(header.name, colIndex) ? 100 : 1\"\n [style.min-height.px]=\"headerRowHeight()\" style=\"height: auto; padding: 8px 6px;\">\n <div class=\"header-content\">\n\n <data-cell [fieldSize]=\"header.field_size\" [columnDatatype]=\"header.dataType\" [columnName]=\"header.name\"\n [value]=\"header.label\" [column]=\"header\" [frozenGrandTotalCell]=\"true\"\n [drillable]=\"header.enableDrilldown || false\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + $index + '_' + header.name\" [eruGridStore]=\"gridStore\" [row]=\"header\">\n </data-cell>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\"\n [title]=\"isAggregationHeader($any(header)) ? 'Edit aggregation' : 'Edit column'\"\n (click)=\"onHeaderDesignClick($event, $any(header))\">tune</mat-icon>\n }\n <!-- <span class=\"header-label header-wrap-text\">{{header.label}}</span> -->\n <!-- <button *ngIf=\"!isRowDimensionHeader(header)\"\n class=\"collapse-toggle-btn\"\n [title]=\"header.isExpanded ? 'Collapse group' : 'Expand group'\"\n (click)=\"toggleColumnGroup(header.groupKey)\"\n type=\"button\">\n <span class=\"collapse-icon\">+</span>\n </button> -->\n </div>\n </th>\n }\n </tr>\n }\n </ng-container>\n } @else {\n <!-- Simple header fallback -->\n <ng-container>\n <tr class=\"pivot-header\" [class.freeze-header-enabled]=\"freezeHeader()\">\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <th [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\" [columnConfig]=\"column\"\n class=\"column-header pivot-column-header\" [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === designTargetFor(column)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 100 : 1\"\n [style.min-height.px]=\"headerRowHeight()\" style=\"height: auto;padding: 8px 6px\">\n <!-- Label and control laid out as a row: the label truncates, the\n control keeps its place. Left as a bare text node the long\n aggregation labels pushed the icon past the cell edge, where\n `overflow: hidden` clipped it out of sight entirely. -->\n <div class=\"pivot-header-content\">\n <!-- Deliberately not `.column-label`: that class carries the\n wrap-headers rule, which broke these labels onto one word per\n line. This header truncates, as it did before. -->\n <span class=\"pivot-header-label\">{{column.label}}</span>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\"\n [title]=\"isAggregationHeader(column) ? 'Edit aggregation' : 'Edit column'\"\n (click)=\"onHeaderDesignClick($event, column)\">tune</mat-icon>\n }\n </div>\n </th>\n }\n </tr>\n </ng-container>\n }\n\n </thead>\n</ng-template>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #pivotColGroup>\n <colgroup>\n @for (column of getLeafColumns(); track trackByColumnFn($index, column)) {\n <col\n [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n </colgroup>\n</ng-template>\n\n<ng-template #pivotGrandTotal>\n <tbody class=\"pivot-tbody\">\n @for (pivotRow of gridStore.pivotGrandTotalData(); track trackByPivotRowFn($index, pivotRow); let i = $index) {\n <tr class=\"pivot-row grand-total-row\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\" [attr.data-pivot-row]=\"i\">\n <!-- <td colspan=\"20\">{{pivotRow | json}}</td> -->\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\" [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\" class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\" [style.height.px]=\"50\" [attr.xx]=\"i\">\n <div class=\"cell-content pivot-cell-content\">\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\" [column]=\"column\" [frozenGrandTotalCell]=\"true\"\n [drillable]=\"column.enableDrilldown || false\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"pivotRow\">\n </data-cell>\n </div>\n </td>\n }\n </tr>\n }\n </tbody>\n</ng-template>\n\n<!-- \u2500\u2500\u2500 Action column cell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n One template for both column positions. With no `config.actions` set it\n falls back to the single more_horiz icon the column has always shown, so\n grids that only listen to the store's actionClick signal keep working.\n Context: { $implicit: Row, mode: 'table' | 'board', group?: RowGroup }\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #actionCell let-row let-mode=\"mode\" let-group=\"group\">\n @if(!hasConfiguredActions()) {\n <mat-icon (click)=\"onActionClick($event, row, undefined, mode || 'table', group)\">more_horiz</mat-icon>\n } @else if(actionDisplayType() === 'kebab') {\n @if(visibleActionsFor(row).length > 0) {\n <mat-icon class=\"action-kebab\" [matMenuTriggerFor]=\"rowActionMenu\"\n [matMenuTriggerData]=\"{ row: row, mode: mode || 'table', group: group }\"\n (click)=\"$event.stopPropagation()\">more_vert</mat-icon>\n }\n } @else {\n <div class=\"action-icons\">\n @for(action of visibleActionsFor(row); track action.action_name) {\n <mat-icon class=\"action-icon\" [matTooltip]=\"action.action_name\" matTooltipPosition=\"above\"\n (click)=\"onActionClick($event, row, action, mode || 'table', group)\">{{action.action_icon || 'play_arrow'}}</mat-icon>\n }\n </div>\n }\n</ng-template>\n\n<!-- Kebab menu shared by every row; the row is passed through matMenuTriggerData. -->\n<mat-menu #rowActionMenu=\"matMenu\" class=\"eru-grid-action-menu\">\n <ng-template matMenuContent let-row=\"row\" let-mode=\"mode\" let-group=\"group\">\n @for(action of visibleActionsFor(row); track action.action_name) {\n <button mat-menu-item (click)=\"onActionClick($event, row, action, mode || 'table', group)\">\n <mat-icon>{{action.action_icon || 'play_arrow'}}</mat-icon>\n <span>{{action.action_name}}</span>\n </button>\n }\n </ng-template>\n</mat-menu>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #tableColGroup>\n <colgroup>\n @if(gridStore.configuration().config.allowSelection) {\n <col style=\"width: 40px; min-width: 40px; max-width: 40px;\">\n }\n @if(shouldShowActionColumn('before')) {\n <col\n [style]=\"'width: ' + actionColumnWidth() + 'px !important; min-width: ' + actionColumnWidth() + 'px !important; max-width: ' + actionColumnWidth() + 'px !important;'\">\n }\n @if(hasHiddenColumns()) {\n <col style=\"width: 40px !important; min-width: 40px !important; max-width: 40px !important;\">\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <col\n [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n @if(shouldShowActionColumn('after')) {\n <col\n [style]=\"'width: ' + actionColumnWidth() + 'px !important; min-width: ' + actionColumnWidth() + 'px !important; max-width: ' + actionColumnWidth() + 'px !important;'\">\n }\n </colgroup>\n</ng-template>\n\n\n<ng-template #tableHeader>\n\n <thead [class.eru-wrap-headers]=\"wrapHeaders()\">\n <tr>\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column column-header table-column-header\">\n <input type=\"checkbox\" [checked]=\"isAllGroupsSelected()\" (change)=\"toggleAllGroups($event)\">\n </th>\n }\n @if(shouldShowActionColumn('before')) {\n <th class=\"action-column column-header table-column-header\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">Action</th>\n }\n @if(hasHiddenColumns()) {\n <th class=\"row-expand-toggle column-header table-column-header\"></th>\n }\n @for (column of visibleColumns(); track trackByColumnFn(i, column); let i = $index) {\n <th [style.width.px]=\"column.field_size\" [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [columnConfig]=\"column\" [index]=\"i\"\n [columnDraggable]=\"gridStore.isFeatureEnabled('columnReorderable') ? i : null\"\n [style.minWidth.px]=\"column.field_size\" class=\"column-header table-column-header\"\n [class.sortable-header]=\"isSortable()\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === column.name\"\n [class.sort-asc]=\"isSortable() && getSortDirection(column.name) === 'asc'\"\n [class.sort-desc]=\"isSortable() && getSortDirection(column.name) === 'desc'\">\n @if(gridStore.isFeatureEnabled('columnReorderable')) {\n <div class=\"column-drag-handle\"></div>\n }\n <span class=\"column-label\" [title]=\"column.tool_tip || column.description || ''\">{{column.label}}</span>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\" title=\"Edit column\" (click)=\"onHeaderDesignClick($event, column)\">tune</mat-icon>\n }\n @if(isSortable()) {\n <span class=\"sort-indicator\">\n <span class=\"sort-triangles\">\n <span class=\"sort-tri sort-tri-up\" [class.sort-tri-active]=\"getSortDirection(column.name) === 'asc'\"\n (click)=\"onSortColumn($event, column, 'asc')\"></span>\n <span class=\"sort-tri sort-tri-down\" [class.sort-tri-active]=\"getSortDirection(column.name) === 'desc'\"\n (click)=\"onSortColumn($event, column, 'desc')\"></span>\n </span>\n @if(getSortPriority(column.name) !== null && gridStore.sortColumns().length > 1) {\n <span class=\"sort-priority\">{{getSortPriority(column.name)}}</span>\n }\n </span>\n }\n </th>\n }\n @if(shouldShowActionColumn('after')) {\n <th class=\"action-column column-header table-column-header\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">Action</th>\n }\n </tr>\n </thead>\n</ng-template>\n\n<!-- Table Subtotal Row Template -->\n<ng-template #tableSubtotal let-group=\"group\">\n <tr class=\"subtotal-row\" [class.subtotal-bold]=\"subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"subTotalStyle() === 'highlighted'\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\"></td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\"></td>\n }\n @for(column of visibleColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"subtotal-cell\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content\">\n @if(colIndex === 0 && getSubtotalValue(group, column.name) === null) {\n <span class=\"subtotal-label\">{{subtotalLabel()}}</span>\n } @else {\n @if(getSubtotalValue(group, column.name) !== null) {\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getSubtotalValue(group, column.name)\" [column]=\"column\" [mode]=\"mode()\" [isEditable]=\"false\"\n [id]=\"'subtotal_' + group.id + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"group.subtotal\">\n </data-cell>\n }\n }\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n </tr>\n</ng-template>\n\n<!-- Table Grand Total Row Template -->\n<ng-template #tableGrandTotal>\n <tr class=\"grand-total-row\" [class.grand-total-bold]=\"grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"grandTotalStyle() === 'highlighted'\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\"></td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\"></td>\n }\n @for(column of visibleColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"grand-total-cell\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content\">\n @if(colIndex === 0 && getGrandTotalValue(column.name) === null) {\n <span class=\"grand-total-label\">Grand Total</span>\n } @else {\n @if(getGrandTotalValue(column.name) !== null) {\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getGrandTotalValue(column.name)\" [column]=\"column\" [mode]=\"mode()\" [isEditable]=\"false\"\n [id]=\"'grandtotal_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"gridStore.rowGrandTotal()\">\n </data-cell>\n }\n }\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n </tr>\n</ng-template>\n\n<!-- \u2500\u2500\u2500 Default board card template \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Used when no boardCardTemplate is passed to <eru-grid>.\n Context: { $implicit: Row, columns: Field[], group: RowGroup }\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #defaultBoardCard let-row let-columns=\"columns\" let-group=\"group\">\n <mat-card class=\"board-card\">\n <mat-card-content>\n @for (column of columns; track column.name) {\n @if ((row?.entity_data?.[column.name] ?? row?.[column.name]) !== undefined) {\n <div class=\"board-card-field\">\n <span class=\"board-field-label\">{{ column.label }}</span>\n <data-cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [column]=\"column\"\n [value]=\"row?.entity_data?.[column.name] ?? row?.[column.name]\"\n [id]=\"row?.entity_id + '_' + column.name\"\n [eruGridStore]=\"gridStore\"\n [mode]=\"'board'\"\n [row]=\"row\">\n </data-cell>\n </div>\n }\n }\n </mat-card-content>\n <mat-card-actions align=\"end\">\n <button mat-icon-button (click)=\"onActionClick($event, row)\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n </mat-card-actions>\n </mat-card>\n</ng-template>", styles: ["@charset \"UTF-8\";:root{--grid-primary: #6750a4;--grid-on-primary: #ffffff;--grid-surface: #fef7ff;--grid-surface-variant: #e7e0ec;--grid-surface-container: #f3edf7;--grid-surface-container-high: #ede7f0;--grid-on-surface: #1d1b20;--grid-on-surface-variant: #49454f;--grid-outline: #79757f;--grid-outline-variant: #cac4d0;--grid-error: #ba1a1a;--grid-error-container: #ffdad6}:host,eru-grid{display:block!important;width:100%;height:100%;flex:1 1 0%;max-height:var(--grid-height, none);min-height:var(--grid-min-height, 120px);font-family:var(--grid-font-family);--grid-font-family: \"Poppins\", \"Roboto\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--grid-font-size-body: 12px;--grid-font-size-caption: 12px !important;--grid-line-height-body: 1;--grid-aggregation-text-align: right;--grid-number-text-align: right;--grid-spacing-xxs: 2px;--grid-spacing-xs: 4px;--grid-spacing-sm: 8px;--grid-spacing-md: 16px;--grid-spacing-lg: 24px;--grid-border-radius: 4px;--grid-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 1px 3px 1px rgba(0, 0, 0, .15);--grid-elevation-2: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 2px 6px 2px rgba(0, 0, 0, .15);--grid-row-hover: var(--grid-surface-variant);--grid-row-selected: var(--grid-surface-container-high);--grid-zebra-odd: transparent;--grid-zebra-even: transparent;--grid-focus-ring: var(--grid-primary);--grid-header-font-weight: 500;--grid-header-text-transform: none;--grid-header-letter-spacing: normal;--grid-header-font-size: var(--grid-font-size-caption);--grid-header-padding-x: 8px;--grid-header-padding-y: 12px;--grid-font-feature-numeric: normal;--grid-cell-padding-x: var(--grid-spacing-xs);--grid-cell-padding-y: var(--grid-spacing-xxs);--grid-tint-subtle: rgba(0, 0, 0, .025);--grid-tint-soft: rgba(0, 0, 0, .045);--grid-tint-strong: rgba(0, 0, 0, .08);--grid-radius-outer: 0;--grid-shadow-outer: none;--grid-divider-color: var(--grid-outline-variant);--grid-divider-width: 1px;--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface);--grid-pill-radius: 999px;--grid-pill-padding-y: 3px;--grid-pill-padding-x: 10px;--grid-pill-font-size: 11px;--grid-pill-font-weight: 500;--grid-priority-dot-size: 8px;--grid-avatar-size: 24px;--grid-avatar-font-size: 10px;--grid-avatar-font-weight: 600;border-radius:var(--grid-radius-outer);box-shadow:var(--grid-shadow-outer)}eru-grid[data-preset=default]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: uppercase;--grid-header-letter-spacing: .06em;--grid-header-font-size: 11px;--grid-header-padding-y: 12px;--grid-header-padding-x: 14px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 14px;--grid-row-hover: var(--grid-tint-subtle);--grid-divider-color: var(--grid-tint-soft);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=modern]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: none;--grid-header-letter-spacing: normal;--grid-header-font-size: 13px;--grid-header-padding-y: 16px;--grid-header-padding-x: 18px;--grid-cell-padding-y: 16px;--grid-cell-padding-x: 18px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-radius-outer: 12px;--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 4px;--grid-pill-padding-x: 12px}eru-grid[data-preset=compact]{--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface);--grid-header-font-weight: 600;--grid-header-text-transform: none;--grid-header-font-size: 11px;--grid-header-padding-y: 4px;--grid-header-padding-x: 8px;--grid-cell-padding-y: 3px;--grid-cell-padding-x: 8px;--grid-font-size-body: 11px;--grid-row-hover: var(--grid-tint-subtle);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 1px;--grid-pill-padding-x: 6px;--grid-pill-font-size: 10px}eru-grid[data-preset=bold]{--grid-header-bg: var(--grid-surface-container-high);--grid-header-color: var(--grid-on-surface);--grid-header-font-weight: 700;--grid-header-text-transform: none;--grid-header-font-size: 13px;--grid-header-padding-y: 14px;--grid-header-padding-x: 12px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 12px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-strong);--grid-divider-width: 1px;--grid-radius-outer: 2px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=financial]{--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: uppercase;--grid-header-letter-spacing: .08em;--grid-header-font-size: 11px;--grid-header-padding-y: 12px;--grid-header-padding-x: 14px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 14px;--grid-zebra-odd: transparent;--grid-zebra-even: var(--grid-tint-subtle);--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=elevated]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 600;--grid-header-text-transform: none;--grid-header-font-size: 12px;--grid-header-padding-y: 16px;--grid-header-padding-x: 18px;--grid-cell-padding-y: 14px;--grid-cell-padding-x: 18px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-radius-outer: 16px;--grid-shadow-outer: 0 1px 3px rgba(0, 0, 0, .06), 0 10px 28px rgba(0, 0, 0, .07);--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 4px;--grid-pill-padding-x: 12px;overflow:hidden}.group-container{padding-bottom:8px}.column-header.design-clickable .design-edit-icon{font-size:16px;width:16px;height:16px;margin-left:4px;opacity:.45;vertical-align:middle;cursor:pointer}.column-header.design-clickable:hover .design-edit-icon,.column-header.design-clickable .design-edit-icon:hover{opacity:1}.column-header.design-selected{background-color:var(--grid-primary-light, rgba(63, 81, 181, .12))}.pivot-column-header .pivot-header-content{display:flex;align-items:center;justify-content:center;gap:4px;min-width:0}.pivot-column-header .pivot-header-content .pivot-header-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.pivot-column-header .pivot-header-content .design-edit-icon,.pivot-column-header .header-content .design-edit-icon{flex:0 0 auto}.pivot-column-header .header-content data-cell,.pivot-column-header .header-content data-cell *{color:inherit!important}.incremental-row-container{width:100%;height:100%;min-height:var(--grid-min-height, 120px);max-height:none;overflow:auto;position:relative;background-color:var(--grid-surface);border-radius:var(--grid-border-radius);font-family:var(--grid-font-family)}.viewport{height:100%;min-height:300px;overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface);scrollbar-gutter:stable}.viewport.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.groups-viewport{height:100%;min-height:300px}.groups-scroll-container{max-height:var(--grid-height, 600px);overflow-y:auto;overflow-x:hidden}.table-viewport{background-color:var(--grid-surface);height:var(--table-height, auto);min-height:var(--table-min-height, 100px);overflow-x:auto;overflow-y:auto}.pivot-viewport{min-height:var(--table-min-height, 300px);overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface)}.pivot-viewport .cdk-virtual-scroll-content-wrapper{width:auto;height:auto}.table-wrapper{min-width:100%;overflow-x:visible}.incremental-row-container .eru-grid-table,.eru-grid-table{width:100%!important;border-collapse:separate;border-spacing:0;table-layout:fixed!important;background-color:var(--grid-surface);color:var(--grid-on-surface);font-family:var(--grid-font-family);font-size:var(--grid-font-size-body);line-height:var(--grid-line-height-body)}.eru-grid-table th,.eru-grid-table td{text-align:left;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;color:var(--grid-on-surface);min-width:0;max-width:100%!important;box-sizing:border-box;position:relative}.eru-grid-table th{background-color:var(--grid-header-bg, var(--grid-surface-container))}thead.eru-wrap-headers th{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;height:auto}thead.eru-wrap-headers th .column-label,thead.eru-wrap-headers th .header-label{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;word-break:break-word;overflow-wrap:anywhere}.eru-grid-table tbody td{background-color:transparent}.eru-grid-table thead{background-color:var(--grid-header-bg, var(--grid-surface-container));transform:translateZ(0);will-change:transform;backface-visibility:hidden}.eru-grid-table thead.freeze-header-enabled{position:sticky!important;top:0!important;z-index:100!important}.eru-grid-table thead th{background-color:var(--grid-header-bg, var(--grid-surface-container));color:var(--grid-header-color, var(--grid-on-surface));font-family:var(--grid-font-family);font-weight:var(--grid-header-font-weight);font-size:var(--grid-header-font-size)}.checkbox-column{width:50px;min-width:50px;max-width:50px;text-align:center;background-color:var(--grid-surface-container)}.checkbox-column input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--grid-primary);border-radius:var(--grid-border-radius)}.checkbox-column input[type=checkbox]:focus{outline:2px solid var(--grid-primary);outline-offset:2px}.action-column{text-align:center;background-color:var(--grid-surface-container)}.action-column mat-icon{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--grid-on-surface-variant);cursor:pointer}.action-column mat-icon:hover{color:var(--grid-primary)}.action-column .action-icons{display:flex;align-items:center;justify-content:center;gap:6px;overflow-x:auto;scrollbar-width:none}.action-column .action-icons::-webkit-scrollbar{display:none}.action-column .action-icon{flex:0 0 auto}.eru-grid-action-menu .mat-mdc-menu-item mat-icon{margin-right:8px;font-size:18px;width:18px;height:18px;line-height:18px;color:var(--grid-on-surface-variant)}.group-header{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-size:var(--grid-font-size-caption);font-weight:500;border-bottom:1px solid var(--grid-outline);cursor:pointer;transition:background-color .2s ease}.group-header:hover{background-color:var(--grid-surface-container-high)}.group-header .group-title{font-weight:600;color:var(--grid-primary)}.group-header .group-row-count{color:var(--grid-on-surface-variant);font-size:var(--grid-font-size-caption);margin-left:var(--grid-spacing-sm)}.row-item{background-color:var(--grid-surface);transition:background-color .15s ease}.row-item:nth-child(odd){background-color:var(--grid-zebra-odd, var(--grid-surface))}.row-item:nth-child(2n){background-color:var(--grid-zebra-even, var(--grid-surface))}.row-item:hover{background-color:var(--grid-row-hover)}.required-toggle-row{background-color:var(--grid-surface-container, #f3edf7);border-bottom:1px solid var(--grid-outline-variant, #cac4d0)}.required-toggle-row .required-toggle-cell{padding:4px 8px!important;text-align:center;vertical-align:middle;position:relative}.required-toggle-row .required-toggle-cell .required-label{position:absolute;top:2px;left:4px;font-size:10px;color:var(--grid-on-surface-variant, #49454f);font-weight:400;text-transform:lowercase}.required-toggle-row .required-toggle-cell mat-checkbox{display:flex;justify-content:center;align-items:center}.table-column-header{padding:var(--grid-header-padding-y) var(--grid-header-padding-x)}.column-header{font-weight:var(--grid-header-font-weight);text-transform:var(--grid-header-text-transform);letter-spacing:var(--grid-header-letter-spacing);text-align:center!important;font-size:var(--grid-header-font-size);position:relative;-webkit-user-select:none;user-select:none;background-color:var(--grid-header-bg, var(--grid-surface-container));color:var(--grid-header-color, var(--grid-on-surface))}.column-header:hover{background-color:var(--grid-header-hover-bg, var(--grid-surface-container-high))}.column-drag-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:grab;opacity:0;transition:opacity .2s ease,background-color .2s ease;z-index:2;display:flex;align-items:center;justify-content:center;border-right:1px solid transparent}.column-drag-handle:after{content:\"\\22ee\\22ee\";font-size:14px;color:var(--grid-on-surface-variant);transform:rotate(90deg)}.column-drag-handle:hover{background-color:var(--grid-surface-container-high);border-right-color:var(--grid-outline)}.column-header:hover .column-drag-handle{opacity:1}.column-drag-handle:active{cursor:grabbing}.sortable-header{cursor:pointer}.sortable-header .column-label{flex:1}.sortable-header .sort-indicator{display:inline-flex;align-items:center;gap:2px;margin-left:4px;cursor:pointer;vertical-align:middle;opacity:0;transition:opacity .15s ease}.sortable-header .sort-indicator .sort-triangles{display:flex;flex-direction:column;align-items:center;gap:2px}.sortable-header .sort-indicator .sort-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;cursor:pointer;transition:border-color .15s ease}.sortable-header .sort-indicator .sort-tri-up{border-bottom:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.sortable-header .sort-indicator .sort-tri-down{border-top:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.sortable-header .sort-indicator .sort-tri-active{opacity:1}.sortable-header .sort-indicator .sort-tri-active.sort-tri-up{border-bottom-color:var(--grid-primary, #6750a4)}.sortable-header .sort-indicator .sort-tri-active.sort-tri-down{border-top-color:var(--grid-primary, #6750a4)}.sortable-header .sort-indicator .sort-priority{font-size:9px;font-weight:600;color:var(--grid-primary, #6750a4);line-height:1;min-width:12px;text-align:center}.sortable-header:hover .sort-indicator,.sortable-header.sort-asc .sort-indicator,.sortable-header.sort-desc .sort-indicator{opacity:1}.sortable-header:hover .sort-indicator .sort-tri:not(.sort-tri-active){opacity:.6}.sort-asc,.sort-desc{background-color:var(--grid-surface-container-low, rgba(103, 80, 164, .04))}.dragging{opacity:1;background-color:var(--grid-surface-container);box-shadow:var(--grid-elevation-2)}.drag-over{background-color:var(--grid-surface-container);border-color:var(--grid-primary)}.data-cell{background-color:transparent;color:var(--grid-on-surface);font-family:var(--grid-font-family);font-size:var(--grid-font-size-body);font-feature-settings:var(--grid-font-feature-numeric);padding:var(--grid-cell-padding-y) var(--grid-cell-padding-x)}.cell-content{align-items:center}.cell-content .mdc-text-field{padding:0px var(--grid-spacing-xxs)!important}.cell-display-text{align-items:center;padding:0px var(--grid-spacing-xs)}.ghost-loading-row{background-color:transparent}.ghost-cell-container{padding:var(--grid-spacing-sm)}.ghost-cell{height:20px;width:100%;background-color:var(--grid-surface-container);animation:pulse 1.5s ease-in-out infinite;border-radius:var(--grid-border-radius)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.column-resizer{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;background-color:transparent;transition:background-color .2s ease}.column-resizer:hover{background-color:var(--grid-primary)}.group-separator{height:var(--grid-spacing-sm);background-color:var(--grid-surface-variant)}.group-separator .separator-cell{background-color:var(--grid-surface-variant);border:none;height:var(--grid-spacing-sm)}.error-state{background-color:var(--grid-error-container);color:var(--grid-error);border-color:var(--grid-error)}.error-message{background-color:var(--grid-error);color:#fff;padding:var(--grid-spacing-sm);border-radius:var(--grid-border-radius);font-size:var(--grid-font-size-caption)}.incremental-row-container .eru-grid-table tbody,.incremental-row-container .eru-grid-table{position:relative}.incremental-row-container .eru-grid-table.show-column-lines{border-right:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-top:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-column-lines:not(.freeze-header){border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table:not(.show-column-lines){border:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table thead:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:calc(var(--grid-divider-width, 1px) * 2);background-color:var(--grid-divider-color, var(--grid-outline, #e0e0e0));pointer-events:none;z-index:10}.incremental-row-container .eru-grid-table.show-column-lines thead th,.incremental-row-container .eru-grid-table.show-column-lines tbody td{border-left:var(--grid-divider-width, 1px) solid var(--grid-divider-color, var(--grid-outline, #e0e0e0))!important}.incremental-row-container .eru-grid-table.show-row-lines thead th,.incremental-row-container .eru-grid-table.show-row-lines tbody td{border-bottom:var(--grid-divider-width, 1px) solid var(--grid-divider-color, var(--grid-outline, #e0e0e0))!important}@media(max-width:768px){.incremental-row-container{height:600px}.eru-grid-table th,.eru-grid-table td{font-size:var(--grid-font-size-caption)}.checkbox-column{width:40px;min-width:40px;max-width:40px}}@media(prefers-contrast:high){.eru-grid-table th,.eru-grid-table td{border-width:2px}.row-item:hover{border-width:2px;border-color:var(--grid-primary)}}@media(prefers-reduced-motion:reduce){.row-item,.column-drag-handle,.ghost-cell{transition:none;animation:none}}.pivot-table .nested-header{text-align:center;font-weight:600;background:var(--grid-surface-container)}.pivot-table .nested-header.row-dimension-header{background:var(--grid-surface-container);font-weight:600}.pivot-table .pivot-header-leafcols{padding:0;margin:0;height:0}.pivot-table .pivot-header-level.level-0 .nested-header{font-size:14px;padding:12px 8px}.pivot-table .pivot-header-level.level-1 .nested-header{font-size:13px;padding:10px 6px}.pivot-table .pivot-header-level.level-2 .nested-header{font-size:12px;padding:8px 4px}.pivot-table .nested-header:hover{background:var(--grid-surface-variant);color:var(--grid-primary);transition:all .2s ease}.pivot-table .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-table .pivot-cell-content{display:flex;justify-content:center;align-items:center;min-height:38px}.pivot-table .pivot-repeated-value .cell-content,.pivot-table .pivot-repeated-value .pivot-cell-content{visibility:hidden}.pivot-table .pivot-group-start.row-dimension-cell{border-top:1px solid var(--grid-outline, #79757f)}.pivot-mode .incremental-row-container{display:flex;flex-direction:column;height:auto;max-height:85vh;overflow:auto}.pivot-mode .h-shell{position:relative;width:calc(100% - var(--scrollbar-width, 17px))!important;top:0;z-index:1;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .h-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell{position:relative;bottom:50px;flex-shrink:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .gt-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell table{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.pivot-mode .gt-shell.adjust-bottom-vs{bottom:66px!important}.pivot-mode .gt-shell.adjust-bottom:not(.adjust-bottom-vs){bottom:calc(66px - var(--scrollbar-width, 17px))!important}.pivot-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .header-shell::-webkit-scrollbar{display:none}.pivot-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.pivot-mode .header-shell .eru-grid-table{margin-bottom:0;width:100%;table-layout:fixed}.pivot-mode .header-shell .eru-grid-table thead{background:var(--grid-surface-container)}.pivot-mode .header-shell .eru-grid-table thead th{background:var(--grid-surface-container);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .header-shell .eru-grid-table thead th.sticky-column{position:sticky;background:var(--grid-surface-container);z-index:111}.pivot-mode .header-shell .eru-grid-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-container{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.pivot-mode .pivot-table{width:auto!important;min-width:100%!important;table-layout:fixed!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important}.pivot-mode .pivot-table td,.pivot-mode .pivot-table th{box-sizing:border-box!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-table{table-layout:fixed!important;width:100%!important}.pivot-mode .pivot-table *{max-width:var(--col-width)!important;box-sizing:border-box!important}.pivot-mode .pivot-table colgroup{width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex-basis:var(--col-width)!important;flex:0 0 var(--col-width)!important}.pivot-mode .pivot-table table{width:100%!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important}.pivot-mode .pivot-table[style*=--table-total-width]{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:0 0 var(--col-width)!important;flex-basis:var(--col-width)!important;flex-grow:0!important;flex-shrink:0!important;overflow:hidden!important}.pivot-mode .pivot-table tbody td,.pivot-mode .pivot-table thead th{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.pivot-mode .pivot-table .cell-content,.pivot-mode .pivot-table data-cell{width:100%!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;display:block!important}.pivot-mode .pivot-table table{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-tbody tr.pivot-row{min-height:var(--grid-data-row-height, 50px)!important;height:var(--grid-data-row-height, 50px)!important}.pivot-mode .pivot-tbody tr.pivot-row:hover{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-tbody tr.pivot-row:nth-child(2n){background-color:#00000005}.pivot-mode .pivot-tbody tr.pivot-row td{min-height:var(--grid-data-row-height, 50px)!important;height:var(--grid-data-row-height, 50px)!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content{min-height:calc(var(--grid-data-row-height, 50px) - 2px);display:flex;align-items:center;justify-content:center}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content data-cell{width:100%;min-height:calc(var(--grid-data-row-height, 50px) - 4px);display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.pivot-mode .pivot-cell{vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-mode .pivot-cell .cell-content{display:flex;justify-content:center;align-items:center;min-height:var(--grid-header-row-height, 40px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}.pivot-mode .pivot-table .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.pivot-mode .pivot-table .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .subtotal-row td:first-child{color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row td.aggregated-value{font-weight:500;color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.pivot-mode .pivot-table .subtotal-bold td{font-weight:600!important;font-style:normal!important}.pivot-mode .pivot-table .subtotal-bold td.aggregated-value{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td{font-style:italic!important}.pivot-mode .pivot-table .subtotal-italic td:first-child{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.pivot-mode .pivot-table .subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted td.aggregated-value{font-weight:500!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted:hover,.pivot-mode .pivot-table .subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-row{background-color:var(--grid-surface-container-high)!important;font-weight:700;font-size:var(--grid-font-size-body)}.pivot-mode .pivot-table .grand-total-row td{background-color:var(--grid-surface-container-high)!important;color:var(--grid-on-surface)}.pivot-mode .pivot-table .grand-total-row td:first-child{font-style:normal;font-weight:800;color:var(--grid-primary)}.pivot-mode .pivot-table .grand-total-row td.aggregated-value{font-weight:500;color:var(--grid-primary);font-family:Roboto Mono,monospace}.pivot-mode .pivot-table .grand-total-row:hover,.pivot-mode .pivot-table .grand-total-row:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-bold td{font-weight:700!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-bold td.aggregated-value{font-weight:700!important}.pivot-mode .pivot-table .grand-total-italic td,.pivot-mode .pivot-table .grand-total-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted{background-color:var(--grid-primary)!important;box-shadow:var(--grid-elevation-2)!important}.pivot-mode .pivot-table .grand-total-highlighted td{background-color:var(--grid-primary)!important;color:var(--grid-on-primary)!important;font-weight:500!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-highlighted td.aggregated-value{color:var(--grid-on-primary)!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted:hover,.pivot-mode .pivot-table .grand-total-highlighted:hover td{background-color:var(--grid-primary)!important}.pivot-mode .pivot-table .collapsible-header{position:relative}.pivot-mode .pivot-table .collapsible-header .header-content{display:flex;align-items:center;justify-content:space-between;gap:var(--grid-spacing-xs);padding:var(--grid-spacing-xs) var(--grid-spacing-sm)}.pivot-mode .pivot-table .collapsible-header .header-label{flex:1;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn{background:none;border:none;cursor:pointer;padding:var(--grid-spacing-xxs);margin:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--grid-border-radius);color:var(--grid-on-surface-variant);transition:all .2s ease;font-size:12px;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:hover{background-color:var(--grid-surface-container);color:var(--grid-primary);transform:scale(1.1)}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:focus{outline:2px solid var(--grid-primary);outline-offset:1px}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn .collapse-icon{display:block;line-height:1;font-family:monospace;font-size:14px}.pivot-mode .pivot-table .collapsible-header.expanded .collapse-toggle-btn .collapse-icon{color:var(--grid-primary)}.pivot-mode .pivot-table .collapsible-header.collapsed{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .header-label{font-style:italic;color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .collapse-toggle-btn .collapse-icon{color:var(--grid-outline)}.pivot-mode .pivot-table .collapsible-header:hover{background-color:var(--grid-surface-container)}.pivot-mode .pivot-table .collapsible-header:hover .header-label{color:var(--grid-on-surface)}.pivot-mode .pivot-table .pivot-single-table{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden;min-height:var(--table-min-height)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container{flex-shrink:0;background:var(--grid-surface)!important;overflow-x:auto;overflow-y:hidden;min-height:100px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table{width:auto;min-width:100%;height:auto!important;min-height:100px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th{background:var(--grid-surface-container)!important;padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:40px!important;height:auto!important;position:relative;visibility:visible!important;color:var(--grid-on-surface)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:101!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container{flex:1;overflow:auto;min-height:300px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-viewport{height:100%!important;width:100%!important;overflow-x:auto!important;overflow-y:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table{width:auto;min-width:100%;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td{padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:32px!important;height:auto!important;background:var(--grid-surface)!important;color:var(--grid-on-surface)!important;visibility:visible!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td.sticky-column,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:100!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr{height:auto!important;min-height:50px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr.pivot-row,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr.pivot-row{visibility:visible!important;display:table-row!important}.pivot-mode .pivot-table .collapsed-column-group{background-color:var(--grid-surface-container);border-left:3px solid var(--grid-primary)}.pivot-mode .pivot-table .collapsed-column-group:hover{background-color:var(--grid-surface-container-high)}.pivot-row.subtotal-row{background-color:var(--grid-surface-variant);font-weight:500}.pivot-row.subtotal-row.subtotal-bold{font-weight:500}.pivot-row.subtotal-row.subtotal-italic{font-style:italic}.pivot-row.subtotal-row.subtotal-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.grand-total-row{background-color:var(--grid-surface-container);font-weight:600}.pivot-row.grand-total-row.grand-total-bold{font-weight:800}.pivot-row.grand-total-row.grand-total-italic{font-style:italic}.pivot-row.grand-total-row.grand-total-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.first-visible-row{background-color:#6750a41a!important;position:relative}.pivot-row.first-visible-row:before{content:\"\\1f441\\fe0f First Visible\";position:absolute;top:-20px;left:0;background:var(--grid-primary);color:var(--grid-on-primary);padding:2px 6px;font-size:10px;border-radius:2px;z-index:1000}.header-wrap-text{white-space:pre-wrap;word-break:auto-phrase}.group-header-row{display:flex;align-items:center;justify-content:space-between;width:100%;padding-right:12px}.custom-collapse-header{background-color:var(--grid-surface-variant);padding:8px 20px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:pointer;display:flex;width:fit-content;align-items:center;-webkit-user-select:none;user-select:none;min-width:200px;margin-bottom:10px;position:sticky;left:1px;z-index:116}.custom-collapse-header .collapse-arrow{display:inline-block;margin-right:8px;font-size:12px;color:var(--grid-on-surface-variant);transition:transform .2s ease;transform:rotate(0)}.custom-collapse-header .collapse-arrow.rotate-arrow{transform:rotate(270deg)}.custom-collapse-header .f-12{font-size:12px;color:var(--grid-on-surface)}.custom-collapse-header .group-sort-indicator{display:inline-flex;align-items:center;margin-left:8px}.custom-collapse-header .group-sort-indicator .sort-triangles{display:flex;flex-direction:column;align-items:center;gap:2px}.custom-collapse-header .group-sort-indicator .sort-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;cursor:pointer;transition:border-color .15s ease}.custom-collapse-header .group-sort-indicator .sort-tri-up{border-bottom:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.custom-collapse-header .group-sort-indicator .sort-tri-down{border-top:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.custom-collapse-header .group-sort-indicator .sort-tri-active{opacity:1}.custom-collapse-header .group-sort-indicator .sort-tri-active.sort-tri-up{border-bottom-color:var(--grid-primary, #6750a4)}.custom-collapse-header .group-sort-indicator .sort-tri-active.sort-tri-down{border-top-color:var(--grid-primary, #6750a4)}.excel-download-icon{cursor:pointer}.excel-download-icon:hover{opacity:.75}.excel-download-bar{display:flex;justify-content:flex-end;padding:4px 12px}.table-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.table-mode .header-shell::-webkit-scrollbar{display:none}.table-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.table-mode .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.table-mode .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.table-mode .subtotal-row td:first-child{color:var(--grid-primary)}.table-mode .subtotal-row td.subtotal-cell{font-weight:500}.table-mode .subtotal-row td.subtotal-cell .subtotal-label{font-weight:600;color:var(--grid-primary)}.table-mode .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.table-mode .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.table-mode .subtotal-row.subtotal-bold td{font-weight:600!important;font-style:normal!important}.table-mode .subtotal-row.subtotal-italic td{font-style:italic!important}.table-mode .subtotal-row.subtotal-italic td:first-child{font-weight:600!important}.table-mode .subtotal-row.subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.table-mode .subtotal-row.subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.table-mode .subtotal-row.subtotal-highlighted:hover,.table-mode .subtotal-row.subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.table-mode .subtotal-row-shell{width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.table-mode .subtotal-row-shell::-webkit-scrollbar{display:none}.board-mode-host{overflow:hidden;display:flex;flex-direction:column;max-height:var(--grid-height, 600px)}.board-mode-host .board-view-container{display:flex;flex-direction:column;flex:1;min-height:0}.board-mode-host .board-sort-bar{display:flex;align-items:center;gap:6px;padding:8px 16px;flex-shrink:0;border-bottom:1px solid var(--grid-outline-variant, #cac4d0);background:var(--grid-surface, #fffbfe);overflow-x:auto}.board-mode-host .board-sort-bar .board-sort-label{font-size:12px;font-weight:500;color:var(--grid-on-surface-variant, #49454f);white-space:nowrap}.board-mode-host .board-sort-bar .board-sort-chip{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:16px;border:1px solid var(--grid-outline-variant, #cac4d0);background:var(--grid-surface, #fffbfe);color:var(--grid-on-surface, #1d1b20);font-size:12px;white-space:nowrap}.board-mode-host .board-sort-bar .board-sort-chip-active{background:var(--grid-surface-container);border-color:var(--grid-outline, #79757f);color:var(--grid-on-surface, #1d1b20)}.board-mode-host .board-sort-bar .board-sort-chip-label{pointer-events:none}.board-mode-host .board-sort-bar .board-sort-chip-arrow{font-size:10px;line-height:1;cursor:pointer;padding:2px;border-radius:4px}.board-mode-host .board-sort-bar .board-sort-chip-arrow:hover{background:#00000014}.board-mode-host .board-sort-bar .board-sort-chip-priority{font-size:9px;font-weight:700;background:var(--grid-primary, #6750a4);color:var(--grid-on-primary, #ffffff);border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center}.board-mode-host .board-sort-bar .board-sort-chip-remove{font-size:10px;cursor:pointer;padding:2px;border-radius:4px;color:var(--grid-on-surface-variant, #49454f)}.board-mode-host .board-sort-bar .board-sort-chip-remove:hover{background:#00000014;color:var(--grid-error, #b3261e)}.board-mode-host .board-sort-bar .board-sort-add-btn{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:16px;border:1px dashed var(--grid-outline-variant, #cac4d0);background:transparent;color:var(--grid-on-surface-variant, #49454f);font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s ease,border-color .15s ease}.board-mode-host .board-sort-bar .board-sort-add-btn .board-sort-add-icon{font-size:14px;width:14px;height:14px}.board-mode-host .board-sort-bar .board-sort-add-btn:hover{background:var(--grid-surface-container-low, #f7f2fa);border-color:var(--grid-primary, #6750a4);color:var(--grid-primary, #6750a4)}.board-mode-host .board-sort-bar .board-sort-clear{display:inline-flex;align-items:center;padding:4px 10px;border-radius:16px;border:1px solid var(--grid-error, #b3261e);background:transparent;color:var(--grid-error, #b3261e);font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s ease}.board-mode-host .board-sort-bar .board-sort-clear:hover{background:#b3261e14}.board-mode-host .board-columns-wrapper{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--board-col-min-width, 300px),var(--board-col-max-width, 1fr)));grid-auto-rows:auto;align-items:start;gap:16px;flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;align-content:start;justify-content:start}.board-mode-host .board-columns-wrapper.board-columns-nowrap{grid-auto-flow:column;grid-template-columns:none;grid-template-rows:auto;grid-auto-rows:auto;grid-auto-columns:minmax(var(--board-col-min-width, 300px),var(--board-col-max-width, 1fr));overflow-x:auto;overflow-y:hidden}.board-mode-host .board-column{max-height:var(--board-column-height, 420px);min-width:0;display:flex;flex-direction:column;background:var(--grid-surface-container, #f3edf7);border-radius:12px;min-height:0;overflow:hidden}.board-mode-host .board-column.board-column-accented{border-top:3px solid var(--board-group-color, transparent)}.board-mode-host .board-column .column-header{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;font-weight:600;flex-shrink:0}.board-mode-host .board-column .column-header:hover{background-color:transparent}.board-mode-host .board-column .column-header .column-header-title{font-size:15px;font-weight:700;letter-spacing:.2px;line-height:1.2;color:var(--grid-on-surface, #1d1b20);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.board-mode-host .board-column .column-header .column-header-title-cell{display:inline-flex;align-items:center;flex:1 1 auto;min-width:0;overflow:visible;text-overflow:clip}.board-mode-host .board-column .column-header .column-header-title-cell data-cell,.board-mode-host .board-column .column-header .column-header-title-cell .data-cell-component,.board-mode-host .board-column .column-header .column-header-title-cell .container{padding:0!important;margin:0!important;border:none!important;background:transparent!important;min-height:0!important;height:auto!important;width:auto!important;max-width:100%!important;overflow:visible!important}.board-mode-host .board-column .column-header .column-header-title-cell .status-display,.board-mode-host .board-column .column-header .column-header-title-cell .status-display-content,.board-mode-host .board-column .column-header .column-header-title-cell .status-text,.board-mode-host .board-column .column-header .column-header-title-cell .tag-display,.board-mode-host .board-column .column-header .column-header-title-cell .tag-text{max-width:none!important;overflow:visible!important;text-overflow:clip!important}.board-mode-host .board-column .column-header .column-header-count{font-size:10px;font-weight:600;color:var(--eru-board-count-color, var(--grid-on-surface-variant, #49454f));background:var(--eru-board-count-bg, var(--grid-surface-variant, #e7e0ec));border-radius:10px;padding:3px 10px;white-space:nowrap;flex-shrink:0}.board-mode-host .board-column-body{flex:0 1 auto;min-height:0}.board-mode-host .board-card-container{box-sizing:border-box;overflow:hidden;border-radius:8px;transition:background-color .15s ease,box-shadow .15s ease}.board-mode-host .board-card-container.show-row-lines{box-shadow:inset 0 0 0 var(--grid-divider-width, 1px) var(--grid-divider-color, var(--grid-outline, #e0e0e0))}.board-mode-host .board-card-container:hover{background-color:var(--eru-board-card-hover-bg, color-mix(in srgb, var(--mat-sys-primary, #1976d2) 8%, transparent))}.board-mode-host .board-card-container.selected{background-color:var(--eru-board-card-selected-bg, color-mix(in srgb, var(--mat-sys-primary, #1976d2) 14%, transparent));box-shadow:inset 0 0 0 2px var(--eru-board-card-selected-outline, var(--mat-sys-primary, #1976d2))}.board-mode-host .board-card{height:calc(100% - 8px);overflow:hidden;cursor:pointer}.board-mode-host .board-card mat-card-title{font-size:13px}.board-mode-host .board-card mat-card-subtitle{font-size:12px}.board-mode-host .board-card-field{display:flex;flex-direction:column;margin-bottom:4px}.board-mode-host .board-field-label{font-size:10px;color:var(--grid-on-surface-variant, #49454f);font-weight:500;text-transform:uppercase;letter-spacing:.5px}.board-mode-host .board-ghost-card{margin:8px;padding:16px;background:var(--grid-surface, #fef7ff);border-radius:8px;animation:board-pulse 1.5s ease-in-out infinite}.board-mode-host .board-ghost-line{height:12px;background:var(--grid-surface-variant, #e7e0ec);border-radius:4px;margin-bottom:8px}.board-mode-host .board-ghost-line--short{width:60%}@keyframes board-pulse{0%,to{opacity:1}50%{opacity:.5}}th.row-expand-toggle,td.row-expand-toggle{width:40px!important;min-width:40px!important;max-width:40px!important;padding:0!important;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;user-select:none;box-sizing:border-box}.row-expand-icon{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--grid-on-surface-variant);transition:transform .15s ease-in-out}.row-expand-icon.expanded{transform:rotate(90deg)}.row-detail{background:var(--grid-surface-container)}.row-detail .row-detail-cell{padding:var(--grid-spacing-sm) var(--grid-spacing-md);border-bottom:1px solid var(--grid-outline-variant)}.row-detail .row-detail-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--grid-spacing-sm) var(--grid-spacing-md)}.row-detail .row-detail-field{display:flex;flex-direction:column;gap:var(--grid-spacing-xxs);min-width:0}.row-detail .row-detail-label{font-size:var(--grid-font-size-caption);color:var(--grid-on-surface-variant);font-weight:500}.row-detail .row-detail-value{min-width:0}.row-detail .row-detail-value data-cell{display:block;width:100%}\n"], dependencies: [{ kind: "component", type: DataCellComponent, selector: "data-cell", inputs: ["eruGridStore", "fieldSize", "columnDatatype", "columnName", "column", "value", "id", "frozenGrandTotalCell", "td", "drillable", "mode", "isEditable", "row", "personCardTemplate"], outputs: ["tdChange"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i1$3.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1$3.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1$3.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i5.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i5.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i5.MatCardContent, selector: "mat-card-content" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i7.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: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuContent, selector: "ng-template[matMenuContent]" }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: ResizeColumnDirective, selector: "[resizeColumn]", inputs: ["resizeColumn", "index", "columnConfig", "gridConfig"] }, { kind: "directive", type: ColumnDragDirective, selector: "[columnDraggable]", inputs: ["columnDraggable"] }, { kind: "component", type: ColumnDesignPanelComponent, selector: "eru-column-design-panel" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
14564
14625
|
}
|
|
14565
14626
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: EruGridComponent, decorators: [{
|
|
14566
14627
|
type: Component,
|
|
@@ -14580,7 +14641,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
14580
14641
|
ResizeColumnDirective,
|
|
14581
14642
|
ColumnDragDirective,
|
|
14582
14643
|
ColumnDesignPanelComponent
|
|
14583
|
-
], template: "<!-- <div style=\"background: #f0f0f0; font-size: 12px; border-bottom: 1px solid #ccc;\">\ncurrentPivotScrollIndex {{currentPivotScrollIndex()}} |\nfirstDataRowIndex {{firstDataRowIndex()}} |\nfirstTr {{firstTr}} |\nmaxDepth {{maxDepth()}}\n</div> -->\n<div class=\"incremental-row-container eru-grid\" #rowContainer [class.pivot-mode]=\"gridStore.isPivotMode()\"\n [class.table-mode]=\"!gridStore.isPivotMode() && !isBoardMode()\" [class.board-mode-host]=\"isBoardMode()\">\n <eru-column-design-panel></eru-column-design-panel>\n <!-- Pivot Mode Template -->\n @if (gridStore.isPivotMode()) {\n <ng-container>\n <div class=\"pivot-container\" style=\"display: flex; flex-direction: column; height: 100%;\"\n [style]=\"'--table-min-height: ' + getInitialMinHeightPx() + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <!-- Debug info for first visible row -->\n\n\n <div class=\"pivot-single-table\"\n style=\"height: 100%; width: 100%; overflow: hidden; display: flex; flex-direction: column;\">\n @if (freezeHeader()) {\n <div #headerScroller class=\"header-shell\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n @if(grandTotalPosition() === 'before' && freezeGrandTotal()) {\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n }\n </table>\n </div>\n }\n <!-- Virtual Scrolled Table Body -->\n <div>\n <cdk-virtual-scroll-viewport #vp [itemSize]=\"dataRowHeight()\" class=\"viewport pivot-viewport\"\n [class.apply-cdk-width]=\"applyCdkWidth()\" (scrolledIndexChange)=\"onPivotScroll($event)\"\n (scroll)=\"onBodyScroll($event)\" style=\"overflow: auto;\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n @if (!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n }\n <!-- Table Body with Virtual Scrolling -->\n <tbody class=\"pivot-tbody\">\n\n <tr *cdkVirtualFor=\"let pivotRow of gridStore.pivotDisplayData(); \n trackBy: trackByPivotRowFn; \n let i = index\" class=\"pivot-row\" [class.subtotal-row]=\"pivotRow._isSubtotal\"\n [class.grand-total-row]=\"pivotRow._isGrandTotal\"\n [class.subtotal-bold]=\"pivotRow._isSubtotal && subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"pivotRow._isSubtotal && subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"pivotRow._isSubtotal && subTotalStyle() === 'highlighted'\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\" [style.cursor]=\"cursorOnHover() || null\" [attr.data-pivot-row]=\"i\">\n @if ((!pivotRow._isGrandTotal && freezeGrandTotal() ) || (!freezeGrandTotal() )) {\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.pivot-repeated-value]=\"isRepeatedDimensionValue(i, column.name)\"\n [class.pivot-group-start]=\"isPivotGroupStart(i, column.name)\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content pivot-cell-content\">\n <data-cell [personCardTemplate]=\"personCardTemplate\" [class.aggregation]=\"!!column.aggregationFunction\" [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\" [value]=\"pivotRow[column.name]\"\n [column]=\"column\" [drillable]=\"column.enableDrilldown || false\" [mode]=\"mode()\"\n [isEditable]=\"isEditable()\" [id]=\"'pivot_' + i + '_' + column.name\" [eruGridStore]=\"gridStore\"\n [row]=\"pivotRow\">\n </data-cell>\n </div>\n </td>\n }\n } @else {\n <td [style.height.px]=\"dataRowHeight()\" [attr.colspan]=\"getLeafColumns().length\"> </td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n </div>\n @if (freezeGrandTotal() && grandTotalPosition() === 'after') {\n <div #gtScroller class=\"header-shell gt-shell\" [class.adjust-bottom]=\"!applyCdkWidth()\"\n [class.adjust-bottom-vs]=\"adjustScrollWidth()\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n\n </table>\n </div>\n }\n\n\n </div>\n </div>\n </ng-container>\n } @else if (isBoardMode()) {\n <!-- Board Mode Template -->\n <div class=\"board-view-container\">\n @if(showSortBar()) {\n <div class=\"board-sort-bar\">\n <span class=\"board-sort-label\">Sort by:</span>\n @for (entry of gridStore.sortColumns(); track getFieldName(entry)) {\n <span class=\"board-sort-chip board-sort-chip-active\">\n <span class=\"board-sort-chip-label\">{{getColumnLabel(entry)}}</span>\n <span class=\"board-sort-chip-arrow\" (click)=\"onBoardSortChipToggle($event, entry)\">\n @if(!entry.startsWith('-')) { \u25B2 } @else { \u25BC }\n </span>\n @if(gridStore.sortColumns().length > 1) {\n <span class=\"board-sort-chip-priority\">{{getSortPriority(getFieldName(entry))}}</span>\n }\n <span class=\"board-sort-chip-remove\" (click)=\"onBoardSortChipRemove($event, entry)\">\u2715</span>\n </span>\n }\n <button class=\"board-sort-add-btn\" [matMenuTriggerFor]=\"sortFieldMenu\">\n <mat-icon class=\"board-sort-add-icon\">add</mat-icon> Add field\n </button>\n <mat-menu #sortFieldMenu=\"matMenu\" class=\"board-sort-menu\">\n @for (column of columns(); track column.name) {\n <button mat-menu-item (click)=\"onBoardSortFieldSelect(column)\"\n [disabled]=\"getSortDirection(column.name) !== null\">\n @if(getSortDirection(column.name) !== null) {\n <mat-icon>check</mat-icon>\n } @else {\n <mat-icon></mat-icon>\n }\n {{column.label}}\n </button>\n }\n </mat-menu>\n @if(gridStore.sortColumns().length > 0) {\n <button class=\"board-sort-clear\" (click)=\"onBoardSortClear()\">\u2715 Clear</button>\n }\n </div>\n }\n <div class=\"board-columns-wrapper\" [class.board-columns-nowrap]=\"!boardWrapColumns()\">\n @for (group of groups(); track group.id) {\n <div class=\"board-column\" [class.board-column-accented]=\"!!boardGroupColor(group)\"\n [style.--board-group-color]=\"boardGroupColor(group)\">\n <div class=\"column-header\">\n <!-- Render the group value through the same read-only cell renderer a\n data cell uses, so the grouped field's datatype formats itself\n (status/tag pills, dates, numbers) instead of printing raw text. -->\n @if (groupByColumn(); as gcol) {\n <span class=\"column-header-title column-header-title-cell\">\n <data-cell\n [eruGridStore]=\"gridStore\"\n [column]=\"gcol\"\n [columnDatatype]=\"gcol.datatype\"\n [columnName]=\"gcol.name\"\n [value]=\"group.title\"\n [id]=\"'board-group-' + group.id\"\n [fieldSize]=\"0\"\n [isEditable]=\"false\"\n [mode]=\"'board-group-header'\">\n </data-cell>\n </span>\n } @else {\n <span class=\"column-header-title\">{{ group.title }}</span>\n }\n <span class=\"column-header-count\">{{ group.currentLoadedRows || 0 }} of {{ group.totalRowCount || 0 }}</span>\n </div>\n <cdk-virtual-scroll-viewport [itemSize]=\"boardCardSlot\" class=\"board-column-body\"\n (scrolledIndexChange)=\"onBoardScrolledIndexChange($event, group)\">\n <div\n *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id)(); templateCacheSize: 0\"\n class=\"board-card-container\"\n [class.selected]=\"isBoardCardActive(row)\"\n [class.show-row-lines]=\"showRowLines()\"\n [style.height.px]=\"boardCardOuterHeight\"\n [style.padding.px]=\"boardCardPadding\"\n [style.marginBottom.px]=\"boardCardGap\"\n [style.cursor]=\"cursorOnHover() || null\"\n (click)=\"emitRowSelect(row, 'board', group)\">\n <!-- Custom template when consumer provides boardCardTemplate; default card otherwise -->\n <ng-container\n *ngTemplateOutlet=\"boardCardTemplate ?? defaultBoardCard;\n context: { $implicit: row, columns: visibleBoardFields(), group: group }\">\n </ng-container>\n </div>\n </cdk-virtual-scroll-viewport>\n @if (group.isLoading) {\n <div class=\"board-ghost-card\">\n <div class=\"board-ghost-line\"></div>\n <div class=\"board-ghost-line board-ghost-line--short\"></div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else {\n\n <!-- Table Mode Template -->\n <ng-template #excelDownloadIcon>\n <svg class=\"excel-download-icon\" title=\"Download Excel\" (click)=\"onExcelDownloadClick($event)\"\n xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" width=\"24px\" height=\"24px\">\n <path fill=\"#169154\" d=\"M29,6H15.744C14.781,6,14,6.781,14,7.744v7.259h15V6z\" />\n <path fill=\"#18482a\" d=\"M14,33.054v7.202C14,41.219,14.781,42,15.743,42H29v-8.946H14z\" />\n <path fill=\"#0c8045\" d=\"M14 15.003H29V24.005000000000003H14z\" />\n <path fill=\"#17472a\" d=\"M14 24.005H29V33.055H14z\" />\n <g>\n <path fill=\"#29c27f\" d=\"M42.256,6H29v9.003h15V7.744C44,6.781,43.219,6,42.256,6z\" />\n <path fill=\"#27663f\" d=\"M29,33.054V42h13.257C43.219,42,44,41.219,44,40.257v-7.202H29z\" />\n <path fill=\"#19ac65\" d=\"M29 15.003H44V24.005000000000003H29z\" />\n <path fill=\"#129652\" d=\"M29 24.005H44V33.055H29z\" />\n </g>\n <path fill=\"#0c7238\"\n d=\"M22.319,34H5.681C4.753,34,4,33.247,4,32.319V15.681C4,14.753,4.753,14,5.681,14h16.638 C23.247,14,24,14.753,24,15.681v16.638C24,33.247,23.247,34,22.319,34z\" />\n <path fill=\"#fff\"\n d=\"M9.807 19L12.193 19 14.129 22.754 16.175 19 18.404 19 15.333 24 18.474 29 16.123 29 14.013 25.07 11.912 29 9.526 29 12.719 23.982z\" />\n </svg>\n </ng-template>\n @if(showExcelDownload() && !showGroupBar()) {\n <div class=\"excel-download-bar\">\n <ng-container *ngTemplateOutlet=\"excelDownloadIcon\"></ng-container>\n </div>\n }\n <!-- Scrollable groups container \u2014 plain iteration avoids CDK fixed-height estimation errors -->\n <div #groupsScrollContainer class=\"groups-scroll-container\" (scroll)=\"onGroupsViewportScroll($event)\">\n\n @for (group of groups(); track trackByGroupFn($index, group); let i = $index) {\n <div class=\"group-container\"\n [attr.data-group-id]=\"group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id\">\n <!-- Combined sticky header with group info and table -->\n <div style=\"\n background:var(--grid-surface);\n position: sticky;\n top: 0;\n z-index: 115;\n \">\n @if(showGroupBar()) {\n <div class=\"group-header-row\">\n <div class=\"custom-collapse-header\" (click)=\"toggleGroupCollapse(group.id)\">\n <span class=\"collapse-arrow\" [ngClass]=\"{\n 'rotate-arrow': group.isExpanded,\n }\">\u25BC</span>\n <span class=\"f-12\">\n {{ group?.title || \"\" }}\n {{ group?.currentLoadedRows || 0 }} -\n {{ group?.totalRowCount || 0 }} rows...</span>\n @if(groupByField() && isSortable()) {\n <span class=\"group-sort-indicator\">\n <span class=\"sort-triangles\">\n <span class=\"sort-tri sort-tri-up\" [class.sort-tri-active]=\"getSortDirection(groupByField()!) === 'asc'\"\n (click)=\"onGroupSortToggle($event, 'asc')\"></span>\n <span class=\"sort-tri sort-tri-down\"\n [class.sort-tri-active]=\"getSortDirection(groupByField()!) === 'desc'\"\n (click)=\"onGroupSortToggle($event, 'desc')\"></span>\n </span>\n </span>\n }\n </div>\n @if(i === 0 && showExcelDownload()) {\n <ng-container *ngTemplateOutlet=\"excelDownloadIcon\"></ng-container>\n }\n </div>\n }\n\n @if(freezeHeader() && (group.isExpanded || !showGroupBar())) {\n <div #headerScroller class=\"header-shell\" [attr.data-group-id]=\"'header-shell-' + group.id\"\n [style]=\"'--table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <table class=\"eru-grid-table\" [class.freeze-header]=\"freezeHeader()\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"tableColGroup\"></ng-container>\n <ng-container *ngTemplateOutlet=\"tableHeader\"></ng-container>\n <!-- Grand Total row after sticky header (position: before) - only for first group -->\n @if(enableColumnGrandTotal() && grandTotalPositionColumn() === 'before' && hasGrandTotalData() && i === 0) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n </tbody>\n }\n <!-- Subtotal row after sticky header (position: before) -->\n @if(enableColumnSubtotals() && subtotalPositionColumn() === 'before' && hasSubtotalData(group)) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n </tbody>\n }\n </table>\n </div>\n }\n </div>\n @if(group.isExpanded || !showGroupBar()) {\n <ng-container>\n <cdk-virtual-scroll-viewport [attr.data-group-id]=\"group.id\" [itemSize]=\"dataRowHeight()\" class=\"viewport table-viewport\"\n (scrolledIndexChange)=\"onScroll($event, group)\" (scroll)=\"onTableBodyScroll($event)\"\n [style]=\"'--table-height: ' + getGroupContentHeight(group.id) + 'px; --table-min-height: ' + getGroupContentHeight(group.id) + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <div class=\"table-wrapper\">\n <table class=\"eru-grid-table\" [class.show-column-lines]=\"showColumnLines()\"\n [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"tableColGroup\"></ng-container>\n @if(!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"tableHeader\"></ng-container>\n }\n <!-- Grand Total row after normal header (position: before) - only for first group -->\n @if(!freezeHeader() && enableColumnGrandTotal() && grandTotalPositionColumn() === 'before' &&\n hasGrandTotalData() && i === 0) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n </tbody>\n }\n <!-- Subtotal row after normal header (position: before) -->\n @if(!freezeHeader() && enableColumnSubtotals() && subtotalPositionColumn() === 'before' &&\n hasSubtotalData(group)) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n </tbody>\n }\n <tbody>\n @if (columns(); as columnsList) {\n <!-- <tr *ngIf=\"groupItem.type === 'table-header' && groups().length > 1\" style=\"background:#fafafa\">\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isGroupSelected(groupItem.group?.id || '')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleGroupSelection($event, groupItem.group?.id || '')\"\n >\n </th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn;let i =index\"\n style=\"text-align: center;\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"true\"\n [columnConfig]=\"column\"\n [columnDraggable]=\"i\"\n class=\"column-header\">\n <div class=\"column-drag-handle\"></div>\n {{column.label}} {{column.symbol}}\n </th>\n </tr> -->\n <!-- @if(getRowsForGroup(group.id).length > 0 && group.isExpanded) { -->\n <!-- *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id)(); \n trackBy: trackByRowFn; \n let i = index\" -->\n <!-- @for(row of getRowsForGroupSignal(group.id)(); track trackByRowFn($index, row); let i = $index) { -->\n <ng-container\n *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id)(); trackBy: trackByRowFn; let i = index\">\n <tr class=\"row-item\" [attr.data-row-id]=\"i\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\" [style.cursor]=\"cursorOnHover() || null\" (click)=\"emitRowSelect(row, 'table', group)\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\" style=\"text-align: center;\">\n <input type=\"checkbox\" [checked]=\"isRowSelected(row?.entity_id)\"\n (change)=\"toggleRowSelection($event, row)\">\n </td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <ng-container\n *ngTemplateOutlet=\"actionCell; context: { $implicit: row, mode: 'table', group: group }\"></ng-container>\n </td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\" (click)=\"toggleRowExpand(row, i, $event)\">\n <mat-icon class=\"row-expand-icon\" [class.expanded]=\"isRowExpanded(row, i)\">chevron_right</mat-icon>\n </td>\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <td #cell [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n class=\"data-cell\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\"\n [matTooltipClass]=\"'error-message'\" [matTooltip]=\"datacell.error()?'Error: ' + datacell.error():''\"\n matTooltipPosition=\"below\">\n <div class=\"cell-content\">\n <data-cell #datacell [personCardTemplate]=\"personCardTemplate\" [td]=cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\" [value]=\"(row?.['entity_data']?.[column.name] ?? row?.[column.name]) || ''\" [column]=\"column\"\n [mode]=\"mode()\" [isEditable]=\"isEditable() && column.editable !== false && column.editable !== 'false'\" [drillable]=\"column.enableDrilldown || false\"\n [id]=\"i + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"row\"></data-cell>\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <ng-container\n *ngTemplateOutlet=\"actionCell; context: { $implicit: row, mode: 'table', group: group }\"></ng-container>\n </td>\n }\n </tr>\n @if(hasHiddenColumns() && isRowExpanded(row, i)) {\n <tr class=\"row-detail\">\n <td class=\"row-detail-cell\" [attr.colspan]=\"rowDetailColspan()\">\n <div class=\"row-detail-grid\">\n @for (hiddenCol of hiddenColumns(); track trackByColumnFn($index, hiddenCol)) {\n <div class=\"row-detail-field\">\n <span class=\"row-detail-label\">{{hiddenCol.label}}</span>\n <div class=\"row-detail-value\">\n <data-cell [fieldSize]=\"hiddenCol.field_size\" [columnDatatype]=\"hiddenCol.datatype\"\n [columnName]=\"hiddenCol.name\" [value]=\"(row?.['entity_data']?.[hiddenCol.name] ?? row?.[hiddenCol.name]) || ''\"\n [column]=\"hiddenCol\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [drillable]=\"hiddenCol.enableDrilldown || false\"\n [id]=\"'detail_' + i + '_' + hiddenCol.name\" [eruGridStore]=\"gridStore\" [row]=\"row\"></data-cell>\n </div>\n </div>\n }\n </div>\n </td>\n </tr>\n }\n </ng-container>\n <!-- } -->\n <!-- } -->\n @if(group.isLoading && (group.isExpanded || !showGroupBar())) {\n @for(i of [].constructor(ghostRows()); let j = $index; track j) {\n <tr class=\"ghost-loading-row\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column ghost-cell-container\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n class=\"ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column ghost-cell-container\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n </tr>\n }\n }\n <!-- <tr\n *ngIf=\"getRowsForGroup(group.id).length === 0 && !group.isExpanded\"\n class=\"group-separator\"\n >\n <td [attr.colspan]=\"groupSeperatorColSpan()\" class=\"separator-cell\"></td>\n </tr> -->\n <!-- Subtotal row at end of group (position: after) -->\n @if(enableColumnSubtotals() && subtotalPositionColumn() === 'after' && hasSubtotalData(group)) {\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n }\n <!-- Grand Total row at end of group (position: after) - only for last group -->\n @if(enableColumnGrandTotal() && grandTotalPositionColumn() === 'after' && hasGrandTotalData() && i ===\n groups().length - 1) {\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n }\n }\n </tbody>\n </table>\n </div>\n </cdk-virtual-scroll-viewport>\n </ng-container>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Pivot Table Header Template -->\n<ng-template #pivotTableHead>\n <thead [class.eru-wrap-headers]=\"wrapHeaders()\">\n @if (hasNestedHeaders()) {\n <ng-container>\n @for (headerRow of getHeaderRows(); track headerRow; let rowIndex = $index) {\n <tr class=\"pivot-header pivot-header-container\" [class.pivot-header-level]=\"'level-' + rowIndex\">\n @for (header of headerRow; track trackByHeaderFn($index, header); let colIndex = $index) {\n <th [attr.colspan]=\"header.colspan\" [attr.rowspan]=\"header.rowspan\"\n [resizeColumn]=\"isResizablePivotHeader(header)\"\n [columnConfig]=\"getFieldForPivotHeader(header) || $any(header)\"\n class=\"column-header pivot-column-header nested-header\"\n [class.row-dimension-header]=\"isRowDimensionHeader(header)\"\n [class.column-dimension-header]=\"!isRowDimensionHeader(header)\" [class.expanded]=\"header.isExpanded\"\n [class.collapsed]=\"!header.isExpanded\" [class.sticky-column]=\"isStickyColumn(header.name, colIndex)\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === designTargetFor($any(header))\"\n [style.position]=\"isStickyColumn(header.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(header.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(header.name, colIndex) ? 100 : 1\"\n [style.min-height.px]=\"headerRowHeight()\" style=\"height: auto; padding: 8px 6px;\">\n <div class=\"header-content\">\n\n <data-cell [fieldSize]=\"header.field_size\" [columnDatatype]=\"header.dataType\" [columnName]=\"header.name\"\n [value]=\"header.label\" [column]=\"header\" [frozenGrandTotalCell]=\"true\"\n [drillable]=\"header.enableDrilldown || false\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + $index + '_' + header.name\" [eruGridStore]=\"gridStore\" [row]=\"header\">\n </data-cell>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\"\n [title]=\"isAggregationHeader($any(header)) ? 'Edit aggregation' : 'Edit column'\"\n (click)=\"onHeaderDesignClick($event, $any(header))\">tune</mat-icon>\n }\n <!-- <span class=\"header-label header-wrap-text\">{{header.label}}</span> -->\n <!-- <button *ngIf=\"!isRowDimensionHeader(header)\"\n class=\"collapse-toggle-btn\"\n [title]=\"header.isExpanded ? 'Collapse group' : 'Expand group'\"\n (click)=\"toggleColumnGroup(header.groupKey)\"\n type=\"button\">\n <span class=\"collapse-icon\">+</span>\n </button> -->\n </div>\n </th>\n }\n </tr>\n }\n </ng-container>\n } @else {\n <!-- Simple header fallback -->\n <ng-container>\n <tr class=\"pivot-header\" [class.freeze-header-enabled]=\"freezeHeader()\">\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <th [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\" [columnConfig]=\"column\"\n class=\"column-header pivot-column-header\" [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === designTargetFor(column)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 100 : 1\"\n [style.min-height.px]=\"headerRowHeight()\" style=\"height: auto;padding: 8px 6px\">\n <!-- Label and control laid out as a row: the label truncates, the\n control keeps its place. Left as a bare text node the long\n aggregation labels pushed the icon past the cell edge, where\n `overflow: hidden` clipped it out of sight entirely. -->\n <div class=\"pivot-header-content\">\n <!-- Deliberately not `.column-label`: that class carries the\n wrap-headers rule, which broke these labels onto one word per\n line. This header truncates, as it did before. -->\n <span class=\"pivot-header-label\">{{column.label}}</span>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\"\n [title]=\"isAggregationHeader(column) ? 'Edit aggregation' : 'Edit column'\"\n (click)=\"onHeaderDesignClick($event, column)\">tune</mat-icon>\n }\n </div>\n </th>\n }\n </tr>\n </ng-container>\n }\n\n </thead>\n</ng-template>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #pivotColGroup>\n <colgroup>\n @for (column of getLeafColumns(); track trackByColumnFn($index, column)) {\n <col\n [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n </colgroup>\n</ng-template>\n\n<ng-template #pivotGrandTotal>\n <tbody class=\"pivot-tbody\">\n @for (pivotRow of gridStore.pivotGrandTotalData(); track trackByPivotRowFn($index, pivotRow); let i = $index) {\n <tr class=\"pivot-row grand-total-row\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\" [attr.data-pivot-row]=\"i\">\n <!-- <td colspan=\"20\">{{pivotRow | json}}</td> -->\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\" [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\" class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\" [style.height.px]=\"50\" [attr.xx]=\"i\">\n <div class=\"cell-content pivot-cell-content\">\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\" [column]=\"column\" [frozenGrandTotalCell]=\"true\"\n [drillable]=\"column.enableDrilldown || false\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"pivotRow\">\n </data-cell>\n </div>\n </td>\n }\n </tr>\n }\n </tbody>\n</ng-template>\n\n<!-- \u2500\u2500\u2500 Action column cell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n One template for both column positions. With no `config.actions` set it\n falls back to the single more_horiz icon the column has always shown, so\n grids that only listen to the store's actionClick signal keep working.\n Context: { $implicit: Row, mode: 'table' | 'board', group?: RowGroup }\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #actionCell let-row let-mode=\"mode\" let-group=\"group\">\n @if(!hasConfiguredActions()) {\n <mat-icon (click)=\"onActionClick($event, row, undefined, mode || 'table', group)\">more_horiz</mat-icon>\n } @else if(actionDisplayType() === 'kebab') {\n @if(visibleActionsFor(row).length > 0) {\n <mat-icon class=\"action-kebab\" [matMenuTriggerFor]=\"rowActionMenu\"\n [matMenuTriggerData]=\"{ row: row, mode: mode || 'table', group: group }\"\n (click)=\"$event.stopPropagation()\">more_vert</mat-icon>\n }\n } @else {\n <div class=\"action-icons\">\n @for(action of visibleActionsFor(row); track action.action_name) {\n <mat-icon class=\"action-icon\" [matTooltip]=\"action.action_name\" matTooltipPosition=\"above\"\n (click)=\"onActionClick($event, row, action, mode || 'table', group)\">{{action.action_icon || 'play_arrow'}}</mat-icon>\n }\n </div>\n }\n</ng-template>\n\n<!-- Kebab menu shared by every row; the row is passed through matMenuTriggerData. -->\n<mat-menu #rowActionMenu=\"matMenu\" class=\"eru-grid-action-menu\">\n <ng-template matMenuContent let-row=\"row\" let-mode=\"mode\" let-group=\"group\">\n @for(action of visibleActionsFor(row); track action.action_name) {\n <button mat-menu-item (click)=\"onActionClick($event, row, action, mode || 'table', group)\">\n <mat-icon>{{action.action_icon || 'play_arrow'}}</mat-icon>\n <span>{{action.action_name}}</span>\n </button>\n }\n </ng-template>\n</mat-menu>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #tableColGroup>\n <colgroup>\n @if(gridStore.configuration().config.allowSelection) {\n <col style=\"width: 40px; min-width: 40px; max-width: 40px;\">\n }\n @if(shouldShowActionColumn('before')) {\n <col\n [style]=\"'width: ' + actionColumnWidth() + 'px !important; min-width: ' + actionColumnWidth() + 'px !important; max-width: ' + actionColumnWidth() + 'px !important;'\">\n }\n @if(hasHiddenColumns()) {\n <col style=\"width: 40px !important; min-width: 40px !important; max-width: 40px !important;\">\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <col\n [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n @if(shouldShowActionColumn('after')) {\n <col\n [style]=\"'width: ' + actionColumnWidth() + 'px !important; min-width: ' + actionColumnWidth() + 'px !important; max-width: ' + actionColumnWidth() + 'px !important;'\">\n }\n </colgroup>\n</ng-template>\n\n\n<ng-template #tableHeader>\n\n <thead [class.eru-wrap-headers]=\"wrapHeaders()\">\n <tr>\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column column-header table-column-header\">\n <input type=\"checkbox\" [checked]=\"isAllGroupsSelected()\" (change)=\"toggleAllGroups($event)\">\n </th>\n }\n @if(shouldShowActionColumn('before')) {\n <th class=\"action-column column-header table-column-header\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">Action</th>\n }\n @if(hasHiddenColumns()) {\n <th class=\"row-expand-toggle column-header table-column-header\"></th>\n }\n @for (column of visibleColumns(); track trackByColumnFn(i, column); let i = $index) {\n <th [style.width.px]=\"column.field_size\" [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [columnConfig]=\"column\" [index]=\"i\"\n [columnDraggable]=\"gridStore.isFeatureEnabled('columnReorderable') ? i : null\"\n [style.minWidth.px]=\"column.field_size\" class=\"column-header table-column-header\"\n [class.sortable-header]=\"isSortable()\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === column.name\"\n [class.sort-asc]=\"isSortable() && getSortDirection(column.name) === 'asc'\"\n [class.sort-desc]=\"isSortable() && getSortDirection(column.name) === 'desc'\">\n @if(gridStore.isFeatureEnabled('columnReorderable')) {\n <div class=\"column-drag-handle\"></div>\n }\n <span class=\"column-label\" [title]=\"column.tool_tip || column.description || ''\">{{column.label}}</span>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\" title=\"Edit column\" (click)=\"onHeaderDesignClick($event, column)\">tune</mat-icon>\n }\n @if(isSortable()) {\n <span class=\"sort-indicator\">\n <span class=\"sort-triangles\">\n <span class=\"sort-tri sort-tri-up\" [class.sort-tri-active]=\"getSortDirection(column.name) === 'asc'\"\n (click)=\"onSortColumn($event, column, 'asc')\"></span>\n <span class=\"sort-tri sort-tri-down\" [class.sort-tri-active]=\"getSortDirection(column.name) === 'desc'\"\n (click)=\"onSortColumn($event, column, 'desc')\"></span>\n </span>\n @if(getSortPriority(column.name) !== null && gridStore.sortColumns().length > 1) {\n <span class=\"sort-priority\">{{getSortPriority(column.name)}}</span>\n }\n </span>\n }\n </th>\n }\n @if(shouldShowActionColumn('after')) {\n <th class=\"action-column column-header table-column-header\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">Action</th>\n }\n </tr>\n </thead>\n</ng-template>\n\n<!-- Table Subtotal Row Template -->\n<ng-template #tableSubtotal let-group=\"group\">\n <tr class=\"subtotal-row\" [class.subtotal-bold]=\"subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"subTotalStyle() === 'highlighted'\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\"></td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\"></td>\n }\n @for(column of visibleColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"subtotal-cell\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content\">\n @if(colIndex === 0 && getSubtotalValue(group, column.name) === null) {\n <span class=\"subtotal-label\">{{subtotalLabel()}}</span>\n } @else {\n @if(getSubtotalValue(group, column.name) !== null) {\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getSubtotalValue(group, column.name)\" [column]=\"column\" [mode]=\"mode()\" [isEditable]=\"false\"\n [id]=\"'subtotal_' + group.id + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"group.subtotal\">\n </data-cell>\n }\n }\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n </tr>\n</ng-template>\n\n<!-- Table Grand Total Row Template -->\n<ng-template #tableGrandTotal>\n <tr class=\"grand-total-row\" [class.grand-total-bold]=\"grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"grandTotalStyle() === 'highlighted'\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\"></td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\"></td>\n }\n @for(column of visibleColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"grand-total-cell\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content\">\n @if(colIndex === 0 && getGrandTotalValue(column.name) === null) {\n <span class=\"grand-total-label\">Grand Total</span>\n } @else {\n @if(getGrandTotalValue(column.name) !== null) {\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getGrandTotalValue(column.name)\" [column]=\"column\" [mode]=\"mode()\" [isEditable]=\"false\"\n [id]=\"'grandtotal_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"gridStore.rowGrandTotal()\">\n </data-cell>\n }\n }\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n </tr>\n</ng-template>\n\n<!-- \u2500\u2500\u2500 Default board card template \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Used when no boardCardTemplate is passed to <eru-grid>.\n Context: { $implicit: Row, columns: Field[], group: RowGroup }\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #defaultBoardCard let-row let-columns=\"columns\" let-group=\"group\">\n <mat-card class=\"board-card\">\n <mat-card-content>\n @for (column of columns; track column.name) {\n @if ((row?.entity_data?.[column.name] ?? row?.[column.name]) !== undefined) {\n <div class=\"board-card-field\">\n <span class=\"board-field-label\">{{ column.label }}</span>\n <data-cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [column]=\"column\"\n [value]=\"row?.entity_data?.[column.name] ?? row?.[column.name]\"\n [id]=\"row?.entity_id + '_' + column.name\"\n [eruGridStore]=\"gridStore\"\n [mode]=\"'board'\"\n [row]=\"row\">\n </data-cell>\n </div>\n }\n }\n </mat-card-content>\n <mat-card-actions align=\"end\">\n <button mat-icon-button (click)=\"onActionClick($event, row)\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n </mat-card-actions>\n </mat-card>\n</ng-template>", styles: ["@charset \"UTF-8\";:root{--grid-primary: #6750a4;--grid-on-primary: #ffffff;--grid-surface: #fef7ff;--grid-surface-variant: #e7e0ec;--grid-surface-container: #f3edf7;--grid-surface-container-high: #ede7f0;--grid-on-surface: #1d1b20;--grid-on-surface-variant: #49454f;--grid-outline: #79757f;--grid-outline-variant: #cac4d0;--grid-error: #ba1a1a;--grid-error-container: #ffdad6}:host,eru-grid{display:block!important;width:100%;height:100%;flex:1 1 0%;min-height:var(--grid-height, 300px);font-family:var(--grid-font-family);--grid-font-family: \"Poppins\", \"Roboto\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--grid-font-size-body: 12px;--grid-font-size-caption: 12px !important;--grid-line-height-body: 1;--grid-aggregation-text-align: right;--grid-number-text-align: right;--grid-spacing-xxs: 2px;--grid-spacing-xs: 4px;--grid-spacing-sm: 8px;--grid-spacing-md: 16px;--grid-spacing-lg: 24px;--grid-border-radius: 4px;--grid-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 1px 3px 1px rgba(0, 0, 0, .15);--grid-elevation-2: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 2px 6px 2px rgba(0, 0, 0, .15);--grid-row-hover: var(--grid-surface-variant);--grid-row-selected: var(--grid-surface-container-high);--grid-zebra-odd: transparent;--grid-zebra-even: transparent;--grid-focus-ring: var(--grid-primary);--grid-header-font-weight: 500;--grid-header-text-transform: none;--grid-header-letter-spacing: normal;--grid-header-font-size: var(--grid-font-size-caption);--grid-header-padding-x: 8px;--grid-header-padding-y: 12px;--grid-font-feature-numeric: normal;--grid-cell-padding-x: var(--grid-spacing-xs);--grid-cell-padding-y: var(--grid-spacing-xxs);--grid-tint-subtle: rgba(0, 0, 0, .025);--grid-tint-soft: rgba(0, 0, 0, .045);--grid-tint-strong: rgba(0, 0, 0, .08);--grid-radius-outer: 0;--grid-shadow-outer: none;--grid-divider-color: var(--grid-outline-variant);--grid-divider-width: 1px;--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface);--grid-pill-radius: 999px;--grid-pill-padding-y: 3px;--grid-pill-padding-x: 10px;--grid-pill-font-size: 11px;--grid-pill-font-weight: 500;--grid-priority-dot-size: 8px;--grid-avatar-size: 24px;--grid-avatar-font-size: 10px;--grid-avatar-font-weight: 600;border-radius:var(--grid-radius-outer);box-shadow:var(--grid-shadow-outer)}eru-grid[data-preset=default]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: uppercase;--grid-header-letter-spacing: .06em;--grid-header-font-size: 11px;--grid-header-padding-y: 12px;--grid-header-padding-x: 14px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 14px;--grid-row-hover: var(--grid-tint-subtle);--grid-divider-color: var(--grid-tint-soft);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=modern]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: none;--grid-header-letter-spacing: normal;--grid-header-font-size: 13px;--grid-header-padding-y: 16px;--grid-header-padding-x: 18px;--grid-cell-padding-y: 16px;--grid-cell-padding-x: 18px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-radius-outer: 12px;--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 4px;--grid-pill-padding-x: 12px}eru-grid[data-preset=compact]{--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface);--grid-header-font-weight: 600;--grid-header-text-transform: none;--grid-header-font-size: 11px;--grid-header-padding-y: 4px;--grid-header-padding-x: 8px;--grid-cell-padding-y: 3px;--grid-cell-padding-x: 8px;--grid-font-size-body: 11px;--grid-row-hover: var(--grid-tint-subtle);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 1px;--grid-pill-padding-x: 6px;--grid-pill-font-size: 10px}eru-grid[data-preset=bold]{--grid-header-bg: var(--grid-surface-container-high);--grid-header-color: var(--grid-on-surface);--grid-header-font-weight: 700;--grid-header-text-transform: none;--grid-header-font-size: 13px;--grid-header-padding-y: 14px;--grid-header-padding-x: 12px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 12px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-strong);--grid-divider-width: 1px;--grid-radius-outer: 2px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=financial]{--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: uppercase;--grid-header-letter-spacing: .08em;--grid-header-font-size: 11px;--grid-header-padding-y: 12px;--grid-header-padding-x: 14px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 14px;--grid-zebra-odd: transparent;--grid-zebra-even: var(--grid-tint-subtle);--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=elevated]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 600;--grid-header-text-transform: none;--grid-header-font-size: 12px;--grid-header-padding-y: 16px;--grid-header-padding-x: 18px;--grid-cell-padding-y: 14px;--grid-cell-padding-x: 18px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-radius-outer: 16px;--grid-shadow-outer: 0 1px 3px rgba(0, 0, 0, .06), 0 10px 28px rgba(0, 0, 0, .07);--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 4px;--grid-pill-padding-x: 12px;overflow:hidden}.group-container{padding-bottom:8px}.column-header.design-clickable .design-edit-icon{font-size:16px;width:16px;height:16px;margin-left:4px;opacity:.45;vertical-align:middle;cursor:pointer}.column-header.design-clickable:hover .design-edit-icon,.column-header.design-clickable .design-edit-icon:hover{opacity:1}.column-header.design-selected{background-color:var(--grid-primary-light, rgba(63, 81, 181, .12))}.pivot-column-header .pivot-header-content{display:flex;align-items:center;justify-content:center;gap:4px;min-width:0}.pivot-column-header .pivot-header-content .pivot-header-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.pivot-column-header .pivot-header-content .design-edit-icon,.pivot-column-header .header-content .design-edit-icon{flex:0 0 auto}.pivot-column-header .header-content data-cell,.pivot-column-header .header-content data-cell *{color:inherit!important}.incremental-row-container{width:100%;height:100%;min-height:var(--grid-height, 300px);max-height:none;overflow:auto;position:relative;background-color:var(--grid-surface);border-radius:var(--grid-border-radius);font-family:var(--grid-font-family)}.viewport{height:100%;min-height:300px;overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface);scrollbar-gutter:stable}.viewport.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.groups-viewport{height:100%;min-height:300px}.groups-scroll-container{height:var(--grid-height, 600px);overflow-y:auto;overflow-x:hidden}.table-viewport{background-color:var(--grid-surface);height:var(--table-height, auto);min-height:var(--table-min-height, 100px);overflow-x:auto;overflow-y:auto}.pivot-viewport{min-height:var(--table-min-height, 300px);overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface)}.pivot-viewport .cdk-virtual-scroll-content-wrapper{width:auto;height:auto}.table-wrapper{min-width:100%;overflow-x:visible}.incremental-row-container .eru-grid-table,.eru-grid-table{width:100%!important;border-collapse:separate;border-spacing:0;table-layout:fixed!important;background-color:var(--grid-surface);color:var(--grid-on-surface);font-family:var(--grid-font-family);font-size:var(--grid-font-size-body);line-height:var(--grid-line-height-body)}.eru-grid-table th,.eru-grid-table td{text-align:left;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;color:var(--grid-on-surface);min-width:0;max-width:100%!important;box-sizing:border-box;position:relative}.eru-grid-table th{background-color:var(--grid-header-bg, var(--grid-surface-container))}thead.eru-wrap-headers th{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;height:auto}thead.eru-wrap-headers th .column-label,thead.eru-wrap-headers th .header-label{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;word-break:break-word;overflow-wrap:anywhere}.eru-grid-table tbody td{background-color:transparent}.eru-grid-table thead{background-color:var(--grid-header-bg, var(--grid-surface-container));transform:translateZ(0);will-change:transform;backface-visibility:hidden}.eru-grid-table thead.freeze-header-enabled{position:sticky!important;top:0!important;z-index:100!important}.eru-grid-table thead th{background-color:var(--grid-header-bg, var(--grid-surface-container));color:var(--grid-header-color, var(--grid-on-surface));font-family:var(--grid-font-family);font-weight:var(--grid-header-font-weight);font-size:var(--grid-header-font-size)}.checkbox-column{width:50px;min-width:50px;max-width:50px;text-align:center;background-color:var(--grid-surface-container)}.checkbox-column input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--grid-primary);border-radius:var(--grid-border-radius)}.checkbox-column input[type=checkbox]:focus{outline:2px solid var(--grid-primary);outline-offset:2px}.action-column{text-align:center;background-color:var(--grid-surface-container)}.action-column mat-icon{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--grid-on-surface-variant);cursor:pointer}.action-column mat-icon:hover{color:var(--grid-primary)}.action-column .action-icons{display:flex;align-items:center;justify-content:center;gap:6px;overflow-x:auto;scrollbar-width:none}.action-column .action-icons::-webkit-scrollbar{display:none}.action-column .action-icon{flex:0 0 auto}.eru-grid-action-menu .mat-mdc-menu-item mat-icon{margin-right:8px;font-size:18px;width:18px;height:18px;line-height:18px;color:var(--grid-on-surface-variant)}.group-header{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-size:var(--grid-font-size-caption);font-weight:500;border-bottom:1px solid var(--grid-outline);cursor:pointer;transition:background-color .2s ease}.group-header:hover{background-color:var(--grid-surface-container-high)}.group-header .group-title{font-weight:600;color:var(--grid-primary)}.group-header .group-row-count{color:var(--grid-on-surface-variant);font-size:var(--grid-font-size-caption);margin-left:var(--grid-spacing-sm)}.row-item{background-color:var(--grid-surface);transition:background-color .15s ease}.row-item:nth-child(odd){background-color:var(--grid-zebra-odd, var(--grid-surface))}.row-item:nth-child(2n){background-color:var(--grid-zebra-even, var(--grid-surface))}.row-item:hover{background-color:var(--grid-row-hover)}.required-toggle-row{background-color:var(--grid-surface-container, #f3edf7);border-bottom:1px solid var(--grid-outline-variant, #cac4d0)}.required-toggle-row .required-toggle-cell{padding:4px 8px!important;text-align:center;vertical-align:middle;position:relative}.required-toggle-row .required-toggle-cell .required-label{position:absolute;top:2px;left:4px;font-size:10px;color:var(--grid-on-surface-variant, #49454f);font-weight:400;text-transform:lowercase}.required-toggle-row .required-toggle-cell mat-checkbox{display:flex;justify-content:center;align-items:center}.table-column-header{padding:var(--grid-header-padding-y) var(--grid-header-padding-x)}.column-header{font-weight:var(--grid-header-font-weight);text-transform:var(--grid-header-text-transform);letter-spacing:var(--grid-header-letter-spacing);text-align:center!important;font-size:var(--grid-header-font-size);position:relative;-webkit-user-select:none;user-select:none;background-color:var(--grid-header-bg, var(--grid-surface-container));color:var(--grid-header-color, var(--grid-on-surface))}.column-header:hover{background-color:var(--grid-header-hover-bg, var(--grid-surface-container-high))}.column-drag-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:grab;opacity:0;transition:opacity .2s ease,background-color .2s ease;z-index:2;display:flex;align-items:center;justify-content:center;border-right:1px solid transparent}.column-drag-handle:after{content:\"\\22ee\\22ee\";font-size:14px;color:var(--grid-on-surface-variant);transform:rotate(90deg)}.column-drag-handle:hover{background-color:var(--grid-surface-container-high);border-right-color:var(--grid-outline)}.column-header:hover .column-drag-handle{opacity:1}.column-drag-handle:active{cursor:grabbing}.sortable-header{cursor:pointer}.sortable-header .column-label{flex:1}.sortable-header .sort-indicator{display:inline-flex;align-items:center;gap:2px;margin-left:4px;cursor:pointer;vertical-align:middle;opacity:0;transition:opacity .15s ease}.sortable-header .sort-indicator .sort-triangles{display:flex;flex-direction:column;align-items:center;gap:2px}.sortable-header .sort-indicator .sort-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;cursor:pointer;transition:border-color .15s ease}.sortable-header .sort-indicator .sort-tri-up{border-bottom:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.sortable-header .sort-indicator .sort-tri-down{border-top:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.sortable-header .sort-indicator .sort-tri-active{opacity:1}.sortable-header .sort-indicator .sort-tri-active.sort-tri-up{border-bottom-color:var(--grid-primary, #6750a4)}.sortable-header .sort-indicator .sort-tri-active.sort-tri-down{border-top-color:var(--grid-primary, #6750a4)}.sortable-header .sort-indicator .sort-priority{font-size:9px;font-weight:600;color:var(--grid-primary, #6750a4);line-height:1;min-width:12px;text-align:center}.sortable-header:hover .sort-indicator,.sortable-header.sort-asc .sort-indicator,.sortable-header.sort-desc .sort-indicator{opacity:1}.sortable-header:hover .sort-indicator .sort-tri:not(.sort-tri-active){opacity:.6}.sort-asc,.sort-desc{background-color:var(--grid-surface-container-low, rgba(103, 80, 164, .04))}.dragging{opacity:1;background-color:var(--grid-surface-container);box-shadow:var(--grid-elevation-2)}.drag-over{background-color:var(--grid-surface-container);border-color:var(--grid-primary)}.data-cell{background-color:transparent;color:var(--grid-on-surface);font-family:var(--grid-font-family);font-size:var(--grid-font-size-body);font-feature-settings:var(--grid-font-feature-numeric);padding:var(--grid-cell-padding-y) var(--grid-cell-padding-x)}.cell-content{align-items:center}.cell-content .mdc-text-field{padding:0px var(--grid-spacing-xxs)!important}.cell-display-text{align-items:center;padding:0px var(--grid-spacing-xs)}.ghost-loading-row{background-color:transparent}.ghost-cell-container{padding:var(--grid-spacing-sm)}.ghost-cell{height:20px;width:100%;background-color:var(--grid-surface-container);animation:pulse 1.5s ease-in-out infinite;border-radius:var(--grid-border-radius)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.column-resizer{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;background-color:transparent;transition:background-color .2s ease}.column-resizer:hover{background-color:var(--grid-primary)}.group-separator{height:var(--grid-spacing-sm);background-color:var(--grid-surface-variant)}.group-separator .separator-cell{background-color:var(--grid-surface-variant);border:none;height:var(--grid-spacing-sm)}.error-state{background-color:var(--grid-error-container);color:var(--grid-error);border-color:var(--grid-error)}.error-message{background-color:var(--grid-error);color:#fff;padding:var(--grid-spacing-sm);border-radius:var(--grid-border-radius);font-size:var(--grid-font-size-caption)}.incremental-row-container .eru-grid-table tbody,.incremental-row-container .eru-grid-table{position:relative}.incremental-row-container .eru-grid-table.show-column-lines{border-right:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-top:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-column-lines:not(.freeze-header){border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table:not(.show-column-lines){border:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table thead:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:calc(var(--grid-divider-width, 1px) * 2);background-color:var(--grid-divider-color, var(--grid-outline, #e0e0e0));pointer-events:none;z-index:10}.incremental-row-container .eru-grid-table.show-column-lines thead th,.incremental-row-container .eru-grid-table.show-column-lines tbody td{border-left:var(--grid-divider-width, 1px) solid var(--grid-divider-color, var(--grid-outline, #e0e0e0))!important}.incremental-row-container .eru-grid-table.show-row-lines thead th,.incremental-row-container .eru-grid-table.show-row-lines tbody td{border-bottom:var(--grid-divider-width, 1px) solid var(--grid-divider-color, var(--grid-outline, #e0e0e0))!important}@media(max-width:768px){.incremental-row-container{height:600px}.eru-grid-table th,.eru-grid-table td{font-size:var(--grid-font-size-caption)}.checkbox-column{width:40px;min-width:40px;max-width:40px}}@media(prefers-contrast:high){.eru-grid-table th,.eru-grid-table td{border-width:2px}.row-item:hover{border-width:2px;border-color:var(--grid-primary)}}@media(prefers-reduced-motion:reduce){.row-item,.column-drag-handle,.ghost-cell{transition:none;animation:none}}.pivot-table .nested-header{text-align:center;font-weight:600;background:var(--grid-surface-container)}.pivot-table .nested-header.row-dimension-header{background:var(--grid-surface-container);font-weight:600}.pivot-table .pivot-header-leafcols{padding:0;margin:0;height:0}.pivot-table .pivot-header-level.level-0 .nested-header{font-size:14px;padding:12px 8px}.pivot-table .pivot-header-level.level-1 .nested-header{font-size:13px;padding:10px 6px}.pivot-table .pivot-header-level.level-2 .nested-header{font-size:12px;padding:8px 4px}.pivot-table .nested-header:hover{background:var(--grid-surface-variant);color:var(--grid-primary);transition:all .2s ease}.pivot-table .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-table .pivot-cell-content{display:flex;justify-content:center;align-items:center;min-height:38px}.pivot-table .pivot-repeated-value .cell-content,.pivot-table .pivot-repeated-value .pivot-cell-content{visibility:hidden}.pivot-table .pivot-group-start.row-dimension-cell{border-top:1px solid var(--grid-outline, #79757f)}.pivot-mode .incremental-row-container{display:flex;flex-direction:column;height:auto;max-height:85vh;overflow:auto}.pivot-mode .h-shell{position:relative;width:calc(100% - var(--scrollbar-width, 17px))!important;top:0;z-index:1;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .h-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell{position:relative;bottom:50px;flex-shrink:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .gt-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell table{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.pivot-mode .gt-shell.adjust-bottom-vs{bottom:66px!important}.pivot-mode .gt-shell.adjust-bottom:not(.adjust-bottom-vs){bottom:calc(66px - var(--scrollbar-width, 17px))!important}.pivot-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .header-shell::-webkit-scrollbar{display:none}.pivot-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.pivot-mode .header-shell .eru-grid-table{margin-bottom:0;width:100%;table-layout:fixed}.pivot-mode .header-shell .eru-grid-table thead{background:var(--grid-surface-container)}.pivot-mode .header-shell .eru-grid-table thead th{background:var(--grid-surface-container);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .header-shell .eru-grid-table thead th.sticky-column{position:sticky;background:var(--grid-surface-container);z-index:111}.pivot-mode .header-shell .eru-grid-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-container{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.pivot-mode .pivot-table{width:auto!important;min-width:100%!important;table-layout:fixed!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important}.pivot-mode .pivot-table td,.pivot-mode .pivot-table th{box-sizing:border-box!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-table{table-layout:fixed!important;width:100%!important}.pivot-mode .pivot-table *{max-width:var(--col-width)!important;box-sizing:border-box!important}.pivot-mode .pivot-table colgroup{width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex-basis:var(--col-width)!important;flex:0 0 var(--col-width)!important}.pivot-mode .pivot-table table{width:100%!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important}.pivot-mode .pivot-table[style*=--table-total-width]{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:0 0 var(--col-width)!important;flex-basis:var(--col-width)!important;flex-grow:0!important;flex-shrink:0!important;overflow:hidden!important}.pivot-mode .pivot-table tbody td,.pivot-mode .pivot-table thead th{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.pivot-mode .pivot-table .cell-content,.pivot-mode .pivot-table data-cell{width:100%!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;display:block!important}.pivot-mode .pivot-table table{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-tbody tr.pivot-row{min-height:var(--grid-data-row-height, 50px)!important;height:var(--grid-data-row-height, 50px)!important}.pivot-mode .pivot-tbody tr.pivot-row:hover{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-tbody tr.pivot-row:nth-child(2n){background-color:#00000005}.pivot-mode .pivot-tbody tr.pivot-row td{min-height:var(--grid-data-row-height, 50px)!important;height:var(--grid-data-row-height, 50px)!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content{min-height:calc(var(--grid-data-row-height, 50px) - 2px);display:flex;align-items:center;justify-content:center}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content data-cell{width:100%;min-height:calc(var(--grid-data-row-height, 50px) - 4px);display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.pivot-mode .pivot-cell{vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-mode .pivot-cell .cell-content{display:flex;justify-content:center;align-items:center;min-height:var(--grid-header-row-height, 40px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}.pivot-mode .pivot-table .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.pivot-mode .pivot-table .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .subtotal-row td:first-child{color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row td.aggregated-value{font-weight:500;color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.pivot-mode .pivot-table .subtotal-bold td{font-weight:600!important;font-style:normal!important}.pivot-mode .pivot-table .subtotal-bold td.aggregated-value{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td{font-style:italic!important}.pivot-mode .pivot-table .subtotal-italic td:first-child{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.pivot-mode .pivot-table .subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted td.aggregated-value{font-weight:500!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted:hover,.pivot-mode .pivot-table .subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-row{background-color:var(--grid-surface-container-high)!important;font-weight:700;font-size:var(--grid-font-size-body)}.pivot-mode .pivot-table .grand-total-row td{background-color:var(--grid-surface-container-high)!important;color:var(--grid-on-surface)}.pivot-mode .pivot-table .grand-total-row td:first-child{font-style:normal;font-weight:800;color:var(--grid-primary)}.pivot-mode .pivot-table .grand-total-row td.aggregated-value{font-weight:500;color:var(--grid-primary);font-family:Roboto Mono,monospace}.pivot-mode .pivot-table .grand-total-row:hover,.pivot-mode .pivot-table .grand-total-row:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-bold td{font-weight:700!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-bold td.aggregated-value{font-weight:700!important}.pivot-mode .pivot-table .grand-total-italic td,.pivot-mode .pivot-table .grand-total-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted{background-color:var(--grid-primary)!important;box-shadow:var(--grid-elevation-2)!important}.pivot-mode .pivot-table .grand-total-highlighted td{background-color:var(--grid-primary)!important;color:var(--grid-on-primary)!important;font-weight:500!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-highlighted td.aggregated-value{color:var(--grid-on-primary)!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted:hover,.pivot-mode .pivot-table .grand-total-highlighted:hover td{background-color:var(--grid-primary)!important}.pivot-mode .pivot-table .collapsible-header{position:relative}.pivot-mode .pivot-table .collapsible-header .header-content{display:flex;align-items:center;justify-content:space-between;gap:var(--grid-spacing-xs);padding:var(--grid-spacing-xs) var(--grid-spacing-sm)}.pivot-mode .pivot-table .collapsible-header .header-label{flex:1;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn{background:none;border:none;cursor:pointer;padding:var(--grid-spacing-xxs);margin:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--grid-border-radius);color:var(--grid-on-surface-variant);transition:all .2s ease;font-size:12px;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:hover{background-color:var(--grid-surface-container);color:var(--grid-primary);transform:scale(1.1)}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:focus{outline:2px solid var(--grid-primary);outline-offset:1px}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn .collapse-icon{display:block;line-height:1;font-family:monospace;font-size:14px}.pivot-mode .pivot-table .collapsible-header.expanded .collapse-toggle-btn .collapse-icon{color:var(--grid-primary)}.pivot-mode .pivot-table .collapsible-header.collapsed{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .header-label{font-style:italic;color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .collapse-toggle-btn .collapse-icon{color:var(--grid-outline)}.pivot-mode .pivot-table .collapsible-header:hover{background-color:var(--grid-surface-container)}.pivot-mode .pivot-table .collapsible-header:hover .header-label{color:var(--grid-on-surface)}.pivot-mode .pivot-table .pivot-single-table{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden;min-height:var(--table-min-height)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container{flex-shrink:0;background:var(--grid-surface)!important;overflow-x:auto;overflow-y:hidden;min-height:100px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table{width:auto;min-width:100%;height:auto!important;min-height:100px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th{background:var(--grid-surface-container)!important;padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:40px!important;height:auto!important;position:relative;visibility:visible!important;color:var(--grid-on-surface)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:101!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container{flex:1;overflow:auto;min-height:300px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-viewport{height:100%!important;width:100%!important;overflow-x:auto!important;overflow-y:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table{width:auto;min-width:100%;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td{padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:32px!important;height:auto!important;background:var(--grid-surface)!important;color:var(--grid-on-surface)!important;visibility:visible!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td.sticky-column,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:100!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr{height:auto!important;min-height:50px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr.pivot-row,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr.pivot-row{visibility:visible!important;display:table-row!important}.pivot-mode .pivot-table .collapsed-column-group{background-color:var(--grid-surface-container);border-left:3px solid var(--grid-primary)}.pivot-mode .pivot-table .collapsed-column-group:hover{background-color:var(--grid-surface-container-high)}.pivot-row.subtotal-row{background-color:var(--grid-surface-variant);font-weight:500}.pivot-row.subtotal-row.subtotal-bold{font-weight:500}.pivot-row.subtotal-row.subtotal-italic{font-style:italic}.pivot-row.subtotal-row.subtotal-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.grand-total-row{background-color:var(--grid-surface-container);font-weight:600}.pivot-row.grand-total-row.grand-total-bold{font-weight:800}.pivot-row.grand-total-row.grand-total-italic{font-style:italic}.pivot-row.grand-total-row.grand-total-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.first-visible-row{background-color:#6750a41a!important;position:relative}.pivot-row.first-visible-row:before{content:\"\\1f441\\fe0f First Visible\";position:absolute;top:-20px;left:0;background:var(--grid-primary);color:var(--grid-on-primary);padding:2px 6px;font-size:10px;border-radius:2px;z-index:1000}.header-wrap-text{white-space:pre-wrap;word-break:auto-phrase}.group-header-row{display:flex;align-items:center;justify-content:space-between;width:100%;padding-right:12px}.custom-collapse-header{background-color:var(--grid-surface-variant);padding:8px 20px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:pointer;display:flex;width:fit-content;align-items:center;-webkit-user-select:none;user-select:none;min-width:200px;margin-bottom:10px;position:sticky;left:1px;z-index:116}.custom-collapse-header .collapse-arrow{display:inline-block;margin-right:8px;font-size:12px;color:var(--grid-on-surface-variant);transition:transform .2s ease;transform:rotate(0)}.custom-collapse-header .collapse-arrow.rotate-arrow{transform:rotate(270deg)}.custom-collapse-header .f-12{font-size:12px;color:var(--grid-on-surface)}.custom-collapse-header .group-sort-indicator{display:inline-flex;align-items:center;margin-left:8px}.custom-collapse-header .group-sort-indicator .sort-triangles{display:flex;flex-direction:column;align-items:center;gap:2px}.custom-collapse-header .group-sort-indicator .sort-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;cursor:pointer;transition:border-color .15s ease}.custom-collapse-header .group-sort-indicator .sort-tri-up{border-bottom:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.custom-collapse-header .group-sort-indicator .sort-tri-down{border-top:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.custom-collapse-header .group-sort-indicator .sort-tri-active{opacity:1}.custom-collapse-header .group-sort-indicator .sort-tri-active.sort-tri-up{border-bottom-color:var(--grid-primary, #6750a4)}.custom-collapse-header .group-sort-indicator .sort-tri-active.sort-tri-down{border-top-color:var(--grid-primary, #6750a4)}.excel-download-icon{cursor:pointer}.excel-download-icon:hover{opacity:.75}.excel-download-bar{display:flex;justify-content:flex-end;padding:4px 12px}.table-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.table-mode .header-shell::-webkit-scrollbar{display:none}.table-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.table-mode .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.table-mode .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.table-mode .subtotal-row td:first-child{color:var(--grid-primary)}.table-mode .subtotal-row td.subtotal-cell{font-weight:500}.table-mode .subtotal-row td.subtotal-cell .subtotal-label{font-weight:600;color:var(--grid-primary)}.table-mode .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.table-mode .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.table-mode .subtotal-row.subtotal-bold td{font-weight:600!important;font-style:normal!important}.table-mode .subtotal-row.subtotal-italic td{font-style:italic!important}.table-mode .subtotal-row.subtotal-italic td:first-child{font-weight:600!important}.table-mode .subtotal-row.subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.table-mode .subtotal-row.subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.table-mode .subtotal-row.subtotal-highlighted:hover,.table-mode .subtotal-row.subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.table-mode .subtotal-row-shell{width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.table-mode .subtotal-row-shell::-webkit-scrollbar{display:none}.board-mode-host{overflow:hidden;display:flex;flex-direction:column;height:var(--grid-height, 600px)}.board-mode-host .board-view-container{display:flex;flex-direction:column;flex:1;min-height:0}.board-mode-host .board-sort-bar{display:flex;align-items:center;gap:6px;padding:8px 16px;flex-shrink:0;border-bottom:1px solid var(--grid-outline-variant, #cac4d0);background:var(--grid-surface, #fffbfe);overflow-x:auto}.board-mode-host .board-sort-bar .board-sort-label{font-size:12px;font-weight:500;color:var(--grid-on-surface-variant, #49454f);white-space:nowrap}.board-mode-host .board-sort-bar .board-sort-chip{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:16px;border:1px solid var(--grid-outline-variant, #cac4d0);background:var(--grid-surface, #fffbfe);color:var(--grid-on-surface, #1d1b20);font-size:12px;white-space:nowrap}.board-mode-host .board-sort-bar .board-sort-chip-active{background:var(--grid-surface-container);border-color:var(--grid-outline, #79757f);color:var(--grid-on-surface, #1d1b20)}.board-mode-host .board-sort-bar .board-sort-chip-label{pointer-events:none}.board-mode-host .board-sort-bar .board-sort-chip-arrow{font-size:10px;line-height:1;cursor:pointer;padding:2px;border-radius:4px}.board-mode-host .board-sort-bar .board-sort-chip-arrow:hover{background:#00000014}.board-mode-host .board-sort-bar .board-sort-chip-priority{font-size:9px;font-weight:700;background:var(--grid-primary, #6750a4);color:var(--grid-on-primary, #ffffff);border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center}.board-mode-host .board-sort-bar .board-sort-chip-remove{font-size:10px;cursor:pointer;padding:2px;border-radius:4px;color:var(--grid-on-surface-variant, #49454f)}.board-mode-host .board-sort-bar .board-sort-chip-remove:hover{background:#00000014;color:var(--grid-error, #b3261e)}.board-mode-host .board-sort-bar .board-sort-add-btn{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:16px;border:1px dashed var(--grid-outline-variant, #cac4d0);background:transparent;color:var(--grid-on-surface-variant, #49454f);font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s ease,border-color .15s ease}.board-mode-host .board-sort-bar .board-sort-add-btn .board-sort-add-icon{font-size:14px;width:14px;height:14px}.board-mode-host .board-sort-bar .board-sort-add-btn:hover{background:var(--grid-surface-container-low, #f7f2fa);border-color:var(--grid-primary, #6750a4);color:var(--grid-primary, #6750a4)}.board-mode-host .board-sort-bar .board-sort-clear{display:inline-flex;align-items:center;padding:4px 10px;border-radius:16px;border:1px solid var(--grid-error, #b3261e);background:transparent;color:var(--grid-error, #b3261e);font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s ease}.board-mode-host .board-sort-bar .board-sort-clear:hover{background:#b3261e14}.board-mode-host .board-columns-wrapper{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--board-col-min-width, 300px),var(--board-col-max-width, 1fr)));grid-auto-rows:var(--board-column-height, 420px);gap:16px;flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;align-content:start;justify-content:start}.board-mode-host .board-columns-wrapper.board-columns-nowrap{grid-auto-flow:column;grid-template-columns:none;grid-template-rows:var(--board-column-height, 420px);grid-auto-rows:auto;grid-auto-columns:minmax(var(--board-col-min-width, 300px),var(--board-col-max-width, 1fr));overflow-x:auto;overflow-y:hidden}.board-mode-host .board-column{height:var(--board-column-height, 420px);min-width:0;display:flex;flex-direction:column;background:var(--grid-surface-container, #f3edf7);border-radius:12px;min-height:0;overflow:hidden}.board-mode-host .board-column.board-column-accented{border-top:3px solid var(--board-group-color, transparent)}.board-mode-host .board-column .column-header{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;font-weight:600;flex-shrink:0}.board-mode-host .board-column .column-header:hover{background-color:transparent}.board-mode-host .board-column .column-header .column-header-title{font-size:15px;font-weight:700;letter-spacing:.2px;line-height:1.2;color:var(--grid-on-surface, #1d1b20);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.board-mode-host .board-column .column-header .column-header-title-cell{display:inline-flex;align-items:center;flex:1 1 auto;min-width:0;overflow:visible;text-overflow:clip}.board-mode-host .board-column .column-header .column-header-title-cell data-cell,.board-mode-host .board-column .column-header .column-header-title-cell .data-cell-component,.board-mode-host .board-column .column-header .column-header-title-cell .container{padding:0!important;margin:0!important;border:none!important;background:transparent!important;min-height:0!important;height:auto!important;width:auto!important;max-width:100%!important;overflow:visible!important}.board-mode-host .board-column .column-header .column-header-title-cell .status-display,.board-mode-host .board-column .column-header .column-header-title-cell .status-display-content,.board-mode-host .board-column .column-header .column-header-title-cell .status-text,.board-mode-host .board-column .column-header .column-header-title-cell .tag-display,.board-mode-host .board-column .column-header .column-header-title-cell .tag-text{max-width:none!important;overflow:visible!important;text-overflow:clip!important}.board-mode-host .board-column .column-header .column-header-count{font-size:10px;font-weight:600;color:var(--grid-on-surface-variant, #49454f);background:var(--grid-surface-variant, #e7e0ec);border-radius:10px;padding:3px 10px;white-space:nowrap;flex-shrink:0}.board-mode-host .board-column-body{flex:1;min-height:0;height:0}.board-mode-host .board-card-container{box-sizing:border-box;overflow:hidden;border-radius:8px;transition:background-color .15s ease,box-shadow .15s ease}.board-mode-host .board-card-container.show-row-lines{box-shadow:inset 0 0 0 var(--grid-divider-width, 1px) var(--grid-divider-color, var(--grid-outline, #e0e0e0))}.board-mode-host .board-card-container:hover{background-color:var(--eru-board-card-hover-bg, color-mix(in srgb, var(--mat-sys-primary, #1976d2) 8%, transparent))}.board-mode-host .board-card-container.selected{background-color:var(--eru-board-card-selected-bg, color-mix(in srgb, var(--mat-sys-primary, #1976d2) 14%, transparent));box-shadow:inset 0 0 0 2px var(--eru-board-card-selected-outline, var(--mat-sys-primary, #1976d2))}.board-mode-host .board-card{height:calc(100% - 8px);overflow:hidden;cursor:pointer}.board-mode-host .board-card mat-card-title{font-size:13px}.board-mode-host .board-card mat-card-subtitle{font-size:12px}.board-mode-host .board-card-field{display:flex;flex-direction:column;margin-bottom:4px}.board-mode-host .board-field-label{font-size:10px;color:var(--grid-on-surface-variant, #49454f);font-weight:500;text-transform:uppercase;letter-spacing:.5px}.board-mode-host .board-ghost-card{margin:8px;padding:16px;background:var(--grid-surface, #fef7ff);border-radius:8px;animation:board-pulse 1.5s ease-in-out infinite}.board-mode-host .board-ghost-line{height:12px;background:var(--grid-surface-variant, #e7e0ec);border-radius:4px;margin-bottom:8px}.board-mode-host .board-ghost-line--short{width:60%}@keyframes board-pulse{0%,to{opacity:1}50%{opacity:.5}}th.row-expand-toggle,td.row-expand-toggle{width:40px!important;min-width:40px!important;max-width:40px!important;padding:0!important;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;user-select:none;box-sizing:border-box}.row-expand-icon{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--grid-on-surface-variant);transition:transform .15s ease-in-out}.row-expand-icon.expanded{transform:rotate(90deg)}.row-detail{background:var(--grid-surface-container)}.row-detail .row-detail-cell{padding:var(--grid-spacing-sm) var(--grid-spacing-md);border-bottom:1px solid var(--grid-outline-variant)}.row-detail .row-detail-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--grid-spacing-sm) var(--grid-spacing-md)}.row-detail .row-detail-field{display:flex;flex-direction:column;gap:var(--grid-spacing-xxs);min-width:0}.row-detail .row-detail-label{font-size:var(--grid-font-size-caption);color:var(--grid-on-surface-variant);font-weight:500}.row-detail .row-detail-value{min-width:0}.row-detail .row-detail-value data-cell{display:block;width:100%}\n"] }]
|
|
14644
|
+
], template: "<!-- <div style=\"background: #f0f0f0; font-size: 12px; border-bottom: 1px solid #ccc;\">\ncurrentPivotScrollIndex {{currentPivotScrollIndex()}} |\nfirstDataRowIndex {{firstDataRowIndex()}} |\nfirstTr {{firstTr}} |\nmaxDepth {{maxDepth()}}\n</div> -->\n<div class=\"incremental-row-container eru-grid\" #rowContainer [class.pivot-mode]=\"gridStore.isPivotMode()\"\n [class.table-mode]=\"!gridStore.isPivotMode() && !isBoardMode()\" [class.board-mode-host]=\"isBoardMode()\">\n <eru-column-design-panel></eru-column-design-panel>\n <!-- Pivot Mode Template -->\n @if (gridStore.isPivotMode()) {\n <ng-container>\n <div class=\"pivot-container\" style=\"display: flex; flex-direction: column; height: 100%;\"\n [style]=\"'--table-min-height: ' + getInitialMinHeightPx() + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <!-- Debug info for first visible row -->\n\n\n <div class=\"pivot-single-table\"\n style=\"height: 100%; width: 100%; overflow: hidden; display: flex; flex-direction: column;\">\n @if (freezeHeader()) {\n <div #headerScroller class=\"header-shell\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n @if(grandTotalPosition() === 'before' && freezeGrandTotal()) {\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n }\n </table>\n </div>\n }\n <!-- Virtual Scrolled Table Body -->\n <div>\n <cdk-virtual-scroll-viewport #vp [itemSize]=\"dataRowHeight()\" class=\"viewport pivot-viewport\"\n [class.apply-cdk-width]=\"applyCdkWidth()\" (scrolledIndexChange)=\"onPivotScroll($event)\"\n (scroll)=\"onBodyScroll($event)\" style=\"overflow: auto;\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <!-- Column Groups for consistent width -->\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n @if (!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"pivotTableHead\"></ng-container>\n }\n <!-- Table Body with Virtual Scrolling -->\n <tbody class=\"pivot-tbody\">\n\n <tr *cdkVirtualFor=\"let pivotRow of gridStore.pivotDisplayData(); \n trackBy: trackByPivotRowFn; \n let i = index\" class=\"pivot-row\" [class.subtotal-row]=\"pivotRow._isSubtotal\"\n [class.grand-total-row]=\"pivotRow._isGrandTotal\"\n [class.subtotal-bold]=\"pivotRow._isSubtotal && subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"pivotRow._isSubtotal && subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"pivotRow._isSubtotal && subTotalStyle() === 'highlighted'\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\" [style.cursor]=\"cursorOnHover() || null\" [attr.data-pivot-row]=\"i\">\n @if ((!pivotRow._isGrandTotal && freezeGrandTotal() ) || (!freezeGrandTotal() )) {\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.pivot-repeated-value]=\"isRepeatedDimensionValue(i, column.name)\"\n [class.pivot-group-start]=\"isPivotGroupStart(i, column.name)\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content pivot-cell-content\">\n <data-cell [personCardTemplate]=\"personCardTemplate\" [class.aggregation]=\"!!column.aggregationFunction\" [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\" [value]=\"pivotRow[column.name]\"\n [column]=\"column\" [drillable]=\"column.enableDrilldown || false\" [mode]=\"mode()\"\n [isEditable]=\"isEditable()\" [id]=\"'pivot_' + i + '_' + column.name\" [eruGridStore]=\"gridStore\"\n [row]=\"pivotRow\">\n </data-cell>\n </div>\n </td>\n }\n } @else {\n <td [style.height.px]=\"dataRowHeight()\" [attr.colspan]=\"getLeafColumns().length\"> </td>\n }\n </tr>\n </tbody>\n </table>\n </cdk-virtual-scroll-viewport>\n\n </div>\n @if (freezeGrandTotal() && grandTotalPosition() === 'after') {\n <div #gtScroller class=\"header-shell gt-shell\" [class.adjust-bottom]=\"!applyCdkWidth()\"\n [class.adjust-bottom-vs]=\"adjustScrollWidth()\">\n <table class=\"eru-grid-table pivot-table\"\n [style]=\"'width: auto; min-width: 100%; --table-total-width: ' + getInitialTotalWidth() + 'px'\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"pivotColGroup\"></ng-container>\n\n <ng-container *ngTemplateOutlet=\"pivotGrandTotal\"></ng-container>\n\n </table>\n </div>\n }\n\n\n </div>\n </div>\n </ng-container>\n } @else if (isBoardMode()) {\n <!-- Board Mode Template -->\n <div class=\"board-view-container\">\n @if(showSortBar()) {\n <div class=\"board-sort-bar\">\n <span class=\"board-sort-label\">Sort by:</span>\n @for (entry of gridStore.sortColumns(); track getFieldName(entry)) {\n <span class=\"board-sort-chip board-sort-chip-active\">\n <span class=\"board-sort-chip-label\">{{getColumnLabel(entry)}}</span>\n <span class=\"board-sort-chip-arrow\" (click)=\"onBoardSortChipToggle($event, entry)\">\n @if(!entry.startsWith('-')) { \u25B2 } @else { \u25BC }\n </span>\n @if(gridStore.sortColumns().length > 1) {\n <span class=\"board-sort-chip-priority\">{{getSortPriority(getFieldName(entry))}}</span>\n }\n <span class=\"board-sort-chip-remove\" (click)=\"onBoardSortChipRemove($event, entry)\">\u2715</span>\n </span>\n }\n <button class=\"board-sort-add-btn\" [matMenuTriggerFor]=\"sortFieldMenu\">\n <mat-icon class=\"board-sort-add-icon\">add</mat-icon> Add field\n </button>\n <mat-menu #sortFieldMenu=\"matMenu\" class=\"board-sort-menu\">\n @for (column of columns(); track column.name) {\n <button mat-menu-item (click)=\"onBoardSortFieldSelect(column)\"\n [disabled]=\"getSortDirection(column.name) !== null\">\n @if(getSortDirection(column.name) !== null) {\n <mat-icon>check</mat-icon>\n } @else {\n <mat-icon></mat-icon>\n }\n {{column.label}}\n </button>\n }\n </mat-menu>\n @if(gridStore.sortColumns().length > 0) {\n <button class=\"board-sort-clear\" (click)=\"onBoardSortClear()\">\u2715 Clear</button>\n }\n </div>\n }\n <div class=\"board-columns-wrapper\" [class.board-columns-nowrap]=\"!boardWrapColumns()\">\n @for (group of groups(); track group.id) {\n <div class=\"board-column\" [class.board-column-accented]=\"!!boardGroupColor(group)\"\n [style.--board-group-color]=\"boardGroupColor(group)\">\n @if (showBoardColumnHeader()) {\n <div class=\"column-header\">\n <!-- Render the group value through the same read-only cell renderer a\n data cell uses, so the grouped field's datatype formats itself\n (status/tag pills, dates, numbers) instead of printing raw text. -->\n @if (groupByColumn(); as gcol) {\n <span class=\"column-header-title column-header-title-cell\">\n <data-cell\n [eruGridStore]=\"gridStore\"\n [column]=\"gcol\"\n [columnDatatype]=\"gcol.datatype\"\n [columnName]=\"gcol.name\"\n [value]=\"group.title\"\n [id]=\"'board-group-' + group.id\"\n [fieldSize]=\"0\"\n [isEditable]=\"false\"\n [mode]=\"'board-group-header'\">\n </data-cell>\n </span>\n } @else {\n <span class=\"column-header-title\">{{ group.title }}</span>\n }\n <span class=\"column-header-count\">{{ group.currentLoadedRows || 0 }} of {{ group.totalRowCount || 0 }}</span>\n </div>\n }\n <cdk-virtual-scroll-viewport [attr.data-group-id]=\"group.id\" [itemSize]=\"boardCardSlot\" class=\"board-column-body\"\n [style.height.px]=\"boardColumnBodyHeight(group)\"\n (scrolledIndexChange)=\"onBoardScrolledIndexChange($event, group)\">\n <div\n *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id)(); templateCacheSize: 0\"\n class=\"board-card-container\"\n [class.selected]=\"isBoardCardActive(row)\"\n [class.show-row-lines]=\"showRowLines()\"\n [style.height.px]=\"boardCardOuterHeight\"\n [style.padding.px]=\"boardCardPadding\"\n [style.marginBottom.px]=\"boardCardGap\"\n [style.cursor]=\"cursorOnHover() || null\"\n (click)=\"emitRowSelect(row, 'board', group)\">\n <!-- Custom template when consumer provides boardCardTemplate; default card otherwise -->\n <ng-container\n *ngTemplateOutlet=\"boardCardTemplate ?? defaultBoardCard;\n context: { $implicit: row, columns: visibleBoardFields(), group: group }\">\n </ng-container>\n </div>\n </cdk-virtual-scroll-viewport>\n @if (group.isLoading) {\n <div class=\"board-ghost-card\">\n <div class=\"board-ghost-line\"></div>\n <div class=\"board-ghost-line board-ghost-line--short\"></div>\n </div>\n }\n </div>\n }\n </div>\n </div>\n } @else {\n\n <!-- Table Mode Template -->\n <ng-template #excelDownloadIcon>\n <svg class=\"excel-download-icon\" title=\"Download Excel\" (click)=\"onExcelDownloadClick($event)\"\n xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 48 48\" width=\"24px\" height=\"24px\">\n <path fill=\"#169154\" d=\"M29,6H15.744C14.781,6,14,6.781,14,7.744v7.259h15V6z\" />\n <path fill=\"#18482a\" d=\"M14,33.054v7.202C14,41.219,14.781,42,15.743,42H29v-8.946H14z\" />\n <path fill=\"#0c8045\" d=\"M14 15.003H29V24.005000000000003H14z\" />\n <path fill=\"#17472a\" d=\"M14 24.005H29V33.055H14z\" />\n <g>\n <path fill=\"#29c27f\" d=\"M42.256,6H29v9.003h15V7.744C44,6.781,43.219,6,42.256,6z\" />\n <path fill=\"#27663f\" d=\"M29,33.054V42h13.257C43.219,42,44,41.219,44,40.257v-7.202H29z\" />\n <path fill=\"#19ac65\" d=\"M29 15.003H44V24.005000000000003H29z\" />\n <path fill=\"#129652\" d=\"M29 24.005H44V33.055H29z\" />\n </g>\n <path fill=\"#0c7238\"\n d=\"M22.319,34H5.681C4.753,34,4,33.247,4,32.319V15.681C4,14.753,4.753,14,5.681,14h16.638 C23.247,14,24,14.753,24,15.681v16.638C24,33.247,23.247,34,22.319,34z\" />\n <path fill=\"#fff\"\n d=\"M9.807 19L12.193 19 14.129 22.754 16.175 19 18.404 19 15.333 24 18.474 29 16.123 29 14.013 25.07 11.912 29 9.526 29 12.719 23.982z\" />\n </svg>\n </ng-template>\n @if(showExcelDownload() && !showGroupBar()) {\n <div class=\"excel-download-bar\">\n <ng-container *ngTemplateOutlet=\"excelDownloadIcon\"></ng-container>\n </div>\n }\n <!-- Scrollable groups container \u2014 plain iteration avoids CDK fixed-height estimation errors -->\n <div #groupsScrollContainer class=\"groups-scroll-container\" (scroll)=\"onGroupsViewportScroll($event)\">\n\n @for (group of groups(); track trackByGroupFn($index, group); let i = $index) {\n <div class=\"group-container\"\n [attr.data-group-id]=\"group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id\">\n <!-- Combined sticky header with group info and table -->\n <div style=\"\n background:var(--grid-surface);\n position: sticky;\n top: 0;\n z-index: 115;\n \">\n @if(showGroupBar()) {\n <div class=\"group-header-row\">\n <div class=\"custom-collapse-header\" (click)=\"toggleGroupCollapse(group.id)\">\n <span class=\"collapse-arrow\" [ngClass]=\"{\n 'rotate-arrow': group.isExpanded,\n }\">\u25BC</span>\n <span class=\"f-12\">\n {{ group?.title || \"\" }}\n {{ group?.currentLoadedRows || 0 }} -\n {{ group?.totalRowCount || 0 }} rows...</span>\n @if(groupByField() && isSortable()) {\n <span class=\"group-sort-indicator\">\n <span class=\"sort-triangles\">\n <span class=\"sort-tri sort-tri-up\" [class.sort-tri-active]=\"getSortDirection(groupByField()!) === 'asc'\"\n (click)=\"onGroupSortToggle($event, 'asc')\"></span>\n <span class=\"sort-tri sort-tri-down\"\n [class.sort-tri-active]=\"getSortDirection(groupByField()!) === 'desc'\"\n (click)=\"onGroupSortToggle($event, 'desc')\"></span>\n </span>\n </span>\n }\n </div>\n @if(i === 0 && showExcelDownload()) {\n <ng-container *ngTemplateOutlet=\"excelDownloadIcon\"></ng-container>\n }\n </div>\n }\n\n @if(freezeHeader() && (group.isExpanded || !showGroupBar())) {\n <div #headerScroller class=\"header-shell\" [attr.data-group-id]=\"'header-shell-' + group.id\"\n [style]=\"'--table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <table class=\"eru-grid-table\" [class.freeze-header]=\"freezeHeader()\"\n [class.show-column-lines]=\"showColumnLines()\" [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"tableColGroup\"></ng-container>\n <ng-container *ngTemplateOutlet=\"tableHeader\"></ng-container>\n <!-- Grand Total row after sticky header (position: before) - only for first group -->\n @if(enableColumnGrandTotal() && grandTotalPositionColumn() === 'before' && hasGrandTotalData() && i === 0) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n </tbody>\n }\n <!-- Subtotal row after sticky header (position: before) -->\n @if(enableColumnSubtotals() && subtotalPositionColumn() === 'before' && hasSubtotalData(group)) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n </tbody>\n }\n </table>\n </div>\n }\n </div>\n @if(group.isExpanded || !showGroupBar()) {\n <ng-container>\n <cdk-virtual-scroll-viewport [attr.data-group-id]=\"group.id\" [itemSize]=\"dataRowHeight()\" class=\"viewport table-viewport\"\n (scrolledIndexChange)=\"onScroll($event, group)\" (scroll)=\"onTableBodyScroll($event)\"\n [style]=\"'--table-height: ' + getGroupContentHeight(group.id) + 'px; --table-min-height: ' + getGroupContentHeight(group.id) + 'px; --table-total-width: ' + getInitialTotalWidth() + 'px'\">\n <div class=\"table-wrapper\">\n <table class=\"eru-grid-table\" [class.show-column-lines]=\"showColumnLines()\"\n [class.show-row-lines]=\"showRowLines()\">\n <ng-container *ngTemplateOutlet=\"tableColGroup\"></ng-container>\n @if(!freezeHeader()) {\n <ng-container *ngTemplateOutlet=\"tableHeader\"></ng-container>\n }\n <!-- Grand Total row after normal header (position: before) - only for first group -->\n @if(!freezeHeader() && enableColumnGrandTotal() && grandTotalPositionColumn() === 'before' &&\n hasGrandTotalData() && i === 0) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n </tbody>\n }\n <!-- Subtotal row after normal header (position: before) -->\n @if(!freezeHeader() && enableColumnSubtotals() && subtotalPositionColumn() === 'before' &&\n hasSubtotalData(group)) {\n <tbody>\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n </tbody>\n }\n <tbody>\n @if (columns(); as columnsList) {\n <!-- <tr *ngIf=\"groupItem.type === 'table-header' && groups().length > 1\" style=\"background:#fafafa\">\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column\" style=\"text-align: center;\">\n <input\n type=\"checkbox\"\n [checked]=\"isGroupSelected(groupItem.group?.id || '')\"\n (click)=\"$event.stopPropagation()\"\n (change)=\"toggleGroupSelection($event, groupItem.group?.id || '')\"\n >\n </th>\n }\n <th *ngFor=\"let column of columns(); trackBy: trackByColumnFn;let i =index\"\n style=\"text-align: center;\"\n [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"true\"\n [columnConfig]=\"column\"\n [columnDraggable]=\"i\"\n class=\"column-header\">\n <div class=\"column-drag-handle\"></div>\n {{column.label}} {{column.symbol}}\n </th>\n </tr> -->\n <!-- @if(getRowsForGroup(group.id).length > 0 && group.isExpanded) { -->\n <!-- *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id)(); \n trackBy: trackByRowFn; \n let i = index\" -->\n <!-- @for(row of getRowsForGroupSignal(group.id)(); track trackByRowFn($index, row); let i = $index) { -->\n <ng-container\n *cdkVirtualFor=\"let row of getRowsForGroupSignal(group.id === null || group.id === undefined ? '__NULL_GROUP__' : group.id)(); trackBy: trackByRowFn; let i = index\">\n <tr class=\"row-item\" [attr.data-row-id]=\"i\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\" [style.cursor]=\"cursorOnHover() || null\" (click)=\"emitRowSelect(row, 'table', group)\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\" style=\"text-align: center;\">\n <input type=\"checkbox\" [checked]=\"isRowSelected(row?.entity_id)\"\n (change)=\"toggleRowSelection($event, row)\">\n </td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <ng-container\n *ngTemplateOutlet=\"actionCell; context: { $implicit: row, mode: 'table', group: group }\"></ng-container>\n </td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\" (click)=\"toggleRowExpand(row, i, $event)\">\n <mat-icon class=\"row-expand-icon\" [class.expanded]=\"isRowExpanded(row, i)\">chevron_right</mat-icon>\n </td>\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <td #cell [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n class=\"data-cell\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\"\n [matTooltipClass]=\"'error-message'\" [matTooltip]=\"datacell.error()?'Error: ' + datacell.error():''\"\n matTooltipPosition=\"below\">\n <div class=\"cell-content\">\n <data-cell #datacell [personCardTemplate]=\"personCardTemplate\" [td]=cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\" [value]=\"(row?.['entity_data']?.[column.name] ?? row?.[column.name]) || ''\" [column]=\"column\"\n [mode]=\"mode()\" [isEditable]=\"isEditable() && column.editable !== false && column.editable !== 'false'\" [drillable]=\"column.enableDrilldown || false\"\n [id]=\"i + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"row\"></data-cell>\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <ng-container\n *ngTemplateOutlet=\"actionCell; context: { $implicit: row, mode: 'table', group: group }\"></ng-container>\n </td>\n }\n </tr>\n @if(hasHiddenColumns() && isRowExpanded(row, i)) {\n <tr class=\"row-detail\">\n <td class=\"row-detail-cell\" [attr.colspan]=\"rowDetailColspan()\">\n <div class=\"row-detail-grid\">\n @for (hiddenCol of hiddenColumns(); track trackByColumnFn($index, hiddenCol)) {\n <div class=\"row-detail-field\">\n <span class=\"row-detail-label\">{{hiddenCol.label}}</span>\n <div class=\"row-detail-value\">\n <data-cell [fieldSize]=\"hiddenCol.field_size\" [columnDatatype]=\"hiddenCol.datatype\"\n [columnName]=\"hiddenCol.name\" [value]=\"(row?.['entity_data']?.[hiddenCol.name] ?? row?.[hiddenCol.name]) || ''\"\n [column]=\"hiddenCol\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [drillable]=\"hiddenCol.enableDrilldown || false\"\n [id]=\"'detail_' + i + '_' + hiddenCol.name\" [eruGridStore]=\"gridStore\" [row]=\"row\"></data-cell>\n </div>\n </div>\n }\n </div>\n </td>\n </tr>\n }\n </ng-container>\n <!-- } -->\n <!-- } -->\n @if(group.isLoading && (group.isExpanded || !showGroupBar())) {\n @for(i of [].constructor(ghostRows()); let j = $index; track j) {\n <tr class=\"ghost-loading-row\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column ghost-cell-container\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n class=\"ghost-cell-container\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column ghost-cell-container\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">\n <div class=\"ghost-cell\"></div>\n </td>\n }\n </tr>\n }\n }\n <!-- <tr\n *ngIf=\"getRowsForGroup(group.id).length === 0 && !group.isExpanded\"\n class=\"group-separator\"\n >\n <td [attr.colspan]=\"groupSeperatorColSpan()\" class=\"separator-cell\"></td>\n </tr> -->\n <!-- Subtotal row at end of group (position: after) -->\n @if(enableColumnSubtotals() && subtotalPositionColumn() === 'after' && hasSubtotalData(group)) {\n <ng-container *ngTemplateOutlet=\"tableSubtotal; context: { group: group }\"></ng-container>\n }\n <!-- Grand Total row at end of group (position: after) - only for last group -->\n @if(enableColumnGrandTotal() && grandTotalPositionColumn() === 'after' && hasGrandTotalData() && i ===\n groups().length - 1) {\n <ng-container *ngTemplateOutlet=\"tableGrandTotal\"></ng-container>\n }\n }\n </tbody>\n </table>\n </div>\n </cdk-virtual-scroll-viewport>\n </ng-container>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Pivot Table Header Template -->\n<ng-template #pivotTableHead>\n <thead [class.eru-wrap-headers]=\"wrapHeaders()\">\n @if (hasNestedHeaders()) {\n <ng-container>\n @for (headerRow of getHeaderRows(); track headerRow; let rowIndex = $index) {\n <tr class=\"pivot-header pivot-header-container\" [class.pivot-header-level]=\"'level-' + rowIndex\">\n @for (header of headerRow; track trackByHeaderFn($index, header); let colIndex = $index) {\n <th [attr.colspan]=\"header.colspan\" [attr.rowspan]=\"header.rowspan\"\n [resizeColumn]=\"isResizablePivotHeader(header)\"\n [columnConfig]=\"getFieldForPivotHeader(header) || $any(header)\"\n class=\"column-header pivot-column-header nested-header\"\n [class.row-dimension-header]=\"isRowDimensionHeader(header)\"\n [class.column-dimension-header]=\"!isRowDimensionHeader(header)\" [class.expanded]=\"header.isExpanded\"\n [class.collapsed]=\"!header.isExpanded\" [class.sticky-column]=\"isStickyColumn(header.name, colIndex)\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === designTargetFor($any(header))\"\n [style.position]=\"isStickyColumn(header.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(header.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(header.name, colIndex) ? 100 : 1\"\n [style.min-height.px]=\"headerRowHeight()\" style=\"height: auto; padding: 8px 6px;\">\n <div class=\"header-content\">\n\n <data-cell [fieldSize]=\"header.field_size\" [columnDatatype]=\"header.dataType\" [columnName]=\"header.name\"\n [value]=\"header.label\" [column]=\"header\" [frozenGrandTotalCell]=\"true\"\n [drillable]=\"header.enableDrilldown || false\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + $index + '_' + header.name\" [eruGridStore]=\"gridStore\" [row]=\"header\">\n </data-cell>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\"\n [title]=\"isAggregationHeader($any(header)) ? 'Edit aggregation' : 'Edit column'\"\n (click)=\"onHeaderDesignClick($event, $any(header))\">tune</mat-icon>\n }\n <!-- <span class=\"header-label header-wrap-text\">{{header.label}}</span> -->\n <!-- <button *ngIf=\"!isRowDimensionHeader(header)\"\n class=\"collapse-toggle-btn\"\n [title]=\"header.isExpanded ? 'Collapse group' : 'Expand group'\"\n (click)=\"toggleColumnGroup(header.groupKey)\"\n type=\"button\">\n <span class=\"collapse-icon\">+</span>\n </button> -->\n </div>\n </th>\n }\n </tr>\n }\n </ng-container>\n } @else {\n <!-- Simple header fallback -->\n <ng-container>\n <tr class=\"pivot-header\" [class.freeze-header-enabled]=\"freezeHeader()\">\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <th [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\"\n [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\" [columnConfig]=\"column\"\n class=\"column-header pivot-column-header\" [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === designTargetFor(column)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 100 : 1\"\n [style.min-height.px]=\"headerRowHeight()\" style=\"height: auto;padding: 8px 6px\">\n <!-- Label and control laid out as a row: the label truncates, the\n control keeps its place. Left as a bare text node the long\n aggregation labels pushed the icon past the cell edge, where\n `overflow: hidden` clipped it out of sight entirely. -->\n <div class=\"pivot-header-content\">\n <!-- Deliberately not `.column-label`: that class carries the\n wrap-headers rule, which broke these labels onto one word per\n line. This header truncates, as it did before. -->\n <span class=\"pivot-header-label\">{{column.label}}</span>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\"\n [title]=\"isAggregationHeader(column) ? 'Edit aggregation' : 'Edit column'\"\n (click)=\"onHeaderDesignClick($event, column)\">tune</mat-icon>\n }\n </div>\n </th>\n }\n </tr>\n </ng-container>\n }\n\n </thead>\n</ng-template>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #pivotColGroup>\n <colgroup>\n @for (column of getLeafColumns(); track trackByColumnFn($index, column)) {\n <col\n [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n </colgroup>\n</ng-template>\n\n<ng-template #pivotGrandTotal>\n <tbody class=\"pivot-tbody\">\n @for (pivotRow of gridStore.pivotGrandTotalData(); track trackByPivotRowFn($index, pivotRow); let i = $index) {\n <tr class=\"pivot-row grand-total-row\"\n [class.grand-total-bold]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"pivotRow._isGrandTotal && grandTotalStyle() === 'highlighted'\"\n [style.height.px]=\"50\" [attr.data-pivot-row]=\"i\">\n <!-- <td colspan=\"20\">{{pivotRow | json}}</td> -->\n @for (column of getLeafColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [attr.rowspan]=\"getEffectiveRowspan(i, column.name)\" [style.width.px]=\"column.field_size\"\n [style.minWidth.px]=\"column.field_size\" class=\"pivot-cell\"\n [class.row-dimension-cell]=\"isRowDimensionColumn(column.name)\"\n [class.column-dimension-cell]=\"!isRowDimensionColumn(column.name)\"\n [class.aggregated-value]=\"!isRowDimensionColumn(column.name) && column.datatype === 'number'\"\n [class.rowspan-cell]=\"getEffectiveRowspan(i, column.name) || 1 > 1\"\n [class.sticky-column]=\"isStickyColumn(column.name, colIndex)\"\n [style.position]=\"isStickyColumn(column.name, colIndex) ? 'sticky' : 'static'\"\n [style.left.px]=\"getStickyColumnLeft(column.name, colIndex)\"\n [style.z-index]=\"isStickyColumn(column.name, colIndex) ? 99 : 1\" [style.height.px]=\"50\" [attr.xx]=\"i\">\n <div class=\"cell-content pivot-cell-content\">\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getEffectiveCellValue(i,column.name, pivotRow)\" [column]=\"column\" [frozenGrandTotalCell]=\"true\"\n [drillable]=\"column.enableDrilldown || false\" [mode]=\"mode()\" [isEditable]=\"isEditable()\"\n [id]=\"'pivot_' + i + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"pivotRow\">\n </data-cell>\n </div>\n </td>\n }\n </tr>\n }\n </tbody>\n</ng-template>\n\n<!-- \u2500\u2500\u2500 Action column cell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n One template for both column positions. With no `config.actions` set it\n falls back to the single more_horiz icon the column has always shown, so\n grids that only listen to the store's actionClick signal keep working.\n Context: { $implicit: Row, mode: 'table' | 'board', group?: RowGroup }\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #actionCell let-row let-mode=\"mode\" let-group=\"group\">\n @if(!hasConfiguredActions()) {\n <mat-icon (click)=\"onActionClick($event, row, undefined, mode || 'table', group)\">more_horiz</mat-icon>\n } @else if(actionDisplayType() === 'kebab') {\n @if(visibleActionsFor(row).length > 0) {\n <mat-icon class=\"action-kebab\" [matMenuTriggerFor]=\"rowActionMenu\"\n [matMenuTriggerData]=\"{ row: row, mode: mode || 'table', group: group }\"\n (click)=\"$event.stopPropagation()\">more_vert</mat-icon>\n }\n } @else {\n <div class=\"action-icons\">\n @for(action of visibleActionsFor(row); track action.action_name) {\n <mat-icon class=\"action-icon\" [matTooltip]=\"action.action_name\" matTooltipPosition=\"above\"\n (click)=\"onActionClick($event, row, action, mode || 'table', group)\">{{action.action_icon || 'play_arrow'}}</mat-icon>\n }\n </div>\n }\n</ng-template>\n\n<!-- Kebab menu shared by every row; the row is passed through matMenuTriggerData. -->\n<mat-menu #rowActionMenu=\"matMenu\" class=\"eru-grid-action-menu\">\n <ng-template matMenuContent let-row=\"row\" let-mode=\"mode\" let-group=\"group\">\n @for(action of visibleActionsFor(row); track action.action_name) {\n <button mat-menu-item (click)=\"onActionClick($event, row, action, mode || 'table', group)\">\n <mat-icon>{{action.action_icon || 'play_arrow'}}</mat-icon>\n <span>{{action.action_name}}</span>\n </button>\n }\n </ng-template>\n</mat-menu>\n\n<!-- Column Group Template for consistent column widths -->\n<ng-template #tableColGroup>\n <colgroup>\n @if(gridStore.configuration().config.allowSelection) {\n <col style=\"width: 40px; min-width: 40px; max-width: 40px;\">\n }\n @if(shouldShowActionColumn('before')) {\n <col\n [style]=\"'width: ' + actionColumnWidth() + 'px !important; min-width: ' + actionColumnWidth() + 'px !important; max-width: ' + actionColumnWidth() + 'px !important;'\">\n }\n @if(hasHiddenColumns()) {\n <col style=\"width: 40px !important; min-width: 40px !important; max-width: 40px !important;\">\n }\n @for (column of visibleColumns(); track trackByColumnFn($index, column)) {\n <col\n [style]=\"'width: ' + column.field_size + 'px !important; min-width: ' + column.field_size + 'px !important; max-width: ' + column.field_size + 'px !important; --col-width: ' + column.field_size + 'px'\">\n }\n @if(shouldShowActionColumn('after')) {\n <col\n [style]=\"'width: ' + actionColumnWidth() + 'px !important; min-width: ' + actionColumnWidth() + 'px !important; max-width: ' + actionColumnWidth() + 'px !important;'\">\n }\n </colgroup>\n</ng-template>\n\n\n<ng-template #tableHeader>\n\n <thead [class.eru-wrap-headers]=\"wrapHeaders()\">\n <tr>\n @if(gridStore.configuration().config.allowSelection) {\n <th class=\"checkbox-column column-header table-column-header\">\n <input type=\"checkbox\" [checked]=\"isAllGroupsSelected()\" (change)=\"toggleAllGroups($event)\">\n </th>\n }\n @if(shouldShowActionColumn('before')) {\n <th class=\"action-column column-header table-column-header\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">Action</th>\n }\n @if(hasHiddenColumns()) {\n <th class=\"row-expand-toggle column-header table-column-header\"></th>\n }\n @for (column of visibleColumns(); track trackByColumnFn(i, column); let i = $index) {\n <th [style.width.px]=\"column.field_size\" [resizeColumn]=\"gridStore.isFeatureEnabled('columnResizable')\"\n [columnConfig]=\"column\" [index]=\"i\"\n [columnDraggable]=\"gridStore.isFeatureEnabled('columnReorderable') ? i : null\"\n [style.minWidth.px]=\"column.field_size\" class=\"column-header table-column-header\"\n [class.sortable-header]=\"isSortable()\"\n [class.design-clickable]=\"isDesignMode()\"\n [class.design-selected]=\"isDesignMode() && gridStore.selectedDesignColumn() === column.name\"\n [class.sort-asc]=\"isSortable() && getSortDirection(column.name) === 'asc'\"\n [class.sort-desc]=\"isSortable() && getSortDirection(column.name) === 'desc'\">\n @if(gridStore.isFeatureEnabled('columnReorderable')) {\n <div class=\"column-drag-handle\"></div>\n }\n <span class=\"column-label\" [title]=\"column.tool_tip || column.description || ''\">{{column.label}}</span>\n @if(isDesignMode()) {\n <mat-icon class=\"design-edit-icon\" title=\"Edit column\" (click)=\"onHeaderDesignClick($event, column)\">tune</mat-icon>\n }\n @if(isSortable()) {\n <span class=\"sort-indicator\">\n <span class=\"sort-triangles\">\n <span class=\"sort-tri sort-tri-up\" [class.sort-tri-active]=\"getSortDirection(column.name) === 'asc'\"\n (click)=\"onSortColumn($event, column, 'asc')\"></span>\n <span class=\"sort-tri sort-tri-down\" [class.sort-tri-active]=\"getSortDirection(column.name) === 'desc'\"\n (click)=\"onSortColumn($event, column, 'desc')\"></span>\n </span>\n @if(getSortPriority(column.name) !== null && gridStore.sortColumns().length > 1) {\n <span class=\"sort-priority\">{{getSortPriority(column.name)}}</span>\n }\n </span>\n }\n </th>\n }\n @if(shouldShowActionColumn('after')) {\n <th class=\"action-column column-header table-column-header\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\">Action</th>\n }\n </tr>\n </thead>\n</ng-template>\n\n<!-- Table Subtotal Row Template -->\n<ng-template #tableSubtotal let-group=\"group\">\n <tr class=\"subtotal-row\" [class.subtotal-bold]=\"subTotalStyle() === 'bold'\"\n [class.subtotal-italic]=\"subTotalStyle() === 'italic'\"\n [class.subtotal-highlighted]=\"subTotalStyle() === 'highlighted'\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\"></td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\"></td>\n }\n @for(column of visibleColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"subtotal-cell\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content\">\n @if(colIndex === 0 && getSubtotalValue(group, column.name) === null) {\n <span class=\"subtotal-label\">{{subtotalLabel()}}</span>\n } @else {\n @if(getSubtotalValue(group, column.name) !== null) {\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getSubtotalValue(group, column.name)\" [column]=\"column\" [mode]=\"mode()\" [isEditable]=\"false\"\n [id]=\"'subtotal_' + group.id + '_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"group.subtotal\">\n </data-cell>\n }\n }\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n </tr>\n</ng-template>\n\n<!-- Table Grand Total Row Template -->\n<ng-template #tableGrandTotal>\n <tr class=\"grand-total-row\" [class.grand-total-bold]=\"grandTotalStyle() === 'bold'\"\n [class.grand-total-italic]=\"grandTotalStyle() === 'italic'\"\n [class.grand-total-highlighted]=\"grandTotalStyle() === 'highlighted'\" [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n @if(gridStore.configuration().config.allowSelection) {\n <td class=\"checkbox-column\"></td>\n }\n @if(shouldShowActionColumn('before')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n @if(hasHiddenColumns()) {\n <td class=\"row-expand-toggle\"></td>\n }\n @for(column of visibleColumns(); track trackByColumnFn($index, column); let colIndex = $index) {\n <td [style.width.px]=\"column.field_size\" [style.minWidth.px]=\"column.field_size\" class=\"grand-total-cell\"\n [style.height.px]=\"dataRowHeight()\" [style.minHeight.px]=\"dataRowHeight()\">\n <div class=\"cell-content\">\n @if(colIndex === 0 && getGrandTotalValue(column.name) === null) {\n <span class=\"grand-total-label\">Grand Total</span>\n } @else {\n @if(getGrandTotalValue(column.name) !== null) {\n <data-cell [fieldSize]=\"column.field_size\" [columnDatatype]=\"column.datatype\" [columnName]=\"column.name\"\n [value]=\"getGrandTotalValue(column.name)\" [column]=\"column\" [mode]=\"mode()\" [isEditable]=\"false\"\n [id]=\"'grandtotal_' + column.name\" [eruGridStore]=\"gridStore\" [row]=\"gridStore.rowGrandTotal()\">\n </data-cell>\n }\n }\n </div>\n </td>\n }\n @if(shouldShowActionColumn('after')) {\n <td class=\"action-column\" [style.width.px]=\"actionColumnWidth()\"\n [style.minWidth.px]=\"actionColumnWidth()\" [style.maxWidth.px]=\"actionColumnWidth()\"></td>\n }\n </tr>\n</ng-template>\n\n<!-- \u2500\u2500\u2500 Default board card template \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Used when no boardCardTemplate is passed to <eru-grid>.\n Context: { $implicit: Row, columns: Field[], group: RowGroup }\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\n<ng-template #defaultBoardCard let-row let-columns=\"columns\" let-group=\"group\">\n <mat-card class=\"board-card\">\n <mat-card-content>\n @for (column of columns; track column.name) {\n @if ((row?.entity_data?.[column.name] ?? row?.[column.name]) !== undefined) {\n <div class=\"board-card-field\">\n <span class=\"board-field-label\">{{ column.label }}</span>\n <data-cell\n [fieldSize]=\"column.field_size\"\n [columnDatatype]=\"column.datatype\"\n [columnName]=\"column.name\"\n [column]=\"column\"\n [value]=\"row?.entity_data?.[column.name] ?? row?.[column.name]\"\n [id]=\"row?.entity_id + '_' + column.name\"\n [eruGridStore]=\"gridStore\"\n [mode]=\"'board'\"\n [row]=\"row\">\n </data-cell>\n </div>\n }\n }\n </mat-card-content>\n <mat-card-actions align=\"end\">\n <button mat-icon-button (click)=\"onActionClick($event, row)\">\n <mat-icon>more_horiz</mat-icon>\n </button>\n </mat-card-actions>\n </mat-card>\n</ng-template>", styles: ["@charset \"UTF-8\";:root{--grid-primary: #6750a4;--grid-on-primary: #ffffff;--grid-surface: #fef7ff;--grid-surface-variant: #e7e0ec;--grid-surface-container: #f3edf7;--grid-surface-container-high: #ede7f0;--grid-on-surface: #1d1b20;--grid-on-surface-variant: #49454f;--grid-outline: #79757f;--grid-outline-variant: #cac4d0;--grid-error: #ba1a1a;--grid-error-container: #ffdad6}:host,eru-grid{display:block!important;width:100%;height:100%;flex:1 1 0%;max-height:var(--grid-height, none);min-height:var(--grid-min-height, 120px);font-family:var(--grid-font-family);--grid-font-family: \"Poppins\", \"Roboto\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;--grid-font-size-body: 12px;--grid-font-size-caption: 12px !important;--grid-line-height-body: 1;--grid-aggregation-text-align: right;--grid-number-text-align: right;--grid-spacing-xxs: 2px;--grid-spacing-xs: 4px;--grid-spacing-sm: 8px;--grid-spacing-md: 16px;--grid-spacing-lg: 24px;--grid-border-radius: 4px;--grid-elevation-1: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 1px 3px 1px rgba(0, 0, 0, .15);--grid-elevation-2: 0px 1px 2px 0px rgba(0, 0, 0, .3), 0px 2px 6px 2px rgba(0, 0, 0, .15);--grid-row-hover: var(--grid-surface-variant);--grid-row-selected: var(--grid-surface-container-high);--grid-zebra-odd: transparent;--grid-zebra-even: transparent;--grid-focus-ring: var(--grid-primary);--grid-header-font-weight: 500;--grid-header-text-transform: none;--grid-header-letter-spacing: normal;--grid-header-font-size: var(--grid-font-size-caption);--grid-header-padding-x: 8px;--grid-header-padding-y: 12px;--grid-font-feature-numeric: normal;--grid-cell-padding-x: var(--grid-spacing-xs);--grid-cell-padding-y: var(--grid-spacing-xxs);--grid-tint-subtle: rgba(0, 0, 0, .025);--grid-tint-soft: rgba(0, 0, 0, .045);--grid-tint-strong: rgba(0, 0, 0, .08);--grid-radius-outer: 0;--grid-shadow-outer: none;--grid-divider-color: var(--grid-outline-variant);--grid-divider-width: 1px;--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface);--grid-pill-radius: 999px;--grid-pill-padding-y: 3px;--grid-pill-padding-x: 10px;--grid-pill-font-size: 11px;--grid-pill-font-weight: 500;--grid-priority-dot-size: 8px;--grid-avatar-size: 24px;--grid-avatar-font-size: 10px;--grid-avatar-font-weight: 600;border-radius:var(--grid-radius-outer);box-shadow:var(--grid-shadow-outer)}eru-grid[data-preset=default]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: uppercase;--grid-header-letter-spacing: .06em;--grid-header-font-size: 11px;--grid-header-padding-y: 12px;--grid-header-padding-x: 14px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 14px;--grid-row-hover: var(--grid-tint-subtle);--grid-divider-color: var(--grid-tint-soft);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=modern]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: none;--grid-header-letter-spacing: normal;--grid-header-font-size: 13px;--grid-header-padding-y: 16px;--grid-header-padding-x: 18px;--grid-cell-padding-y: 16px;--grid-cell-padding-x: 18px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-radius-outer: 12px;--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 4px;--grid-pill-padding-x: 12px}eru-grid[data-preset=compact]{--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface);--grid-header-font-weight: 600;--grid-header-text-transform: none;--grid-header-font-size: 11px;--grid-header-padding-y: 4px;--grid-header-padding-x: 8px;--grid-cell-padding-y: 3px;--grid-cell-padding-x: 8px;--grid-font-size-body: 11px;--grid-row-hover: var(--grid-tint-subtle);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 1px;--grid-pill-padding-x: 6px;--grid-pill-font-size: 10px}eru-grid[data-preset=bold]{--grid-header-bg: var(--grid-surface-container-high);--grid-header-color: var(--grid-on-surface);--grid-header-font-weight: 700;--grid-header-text-transform: none;--grid-header-font-size: 13px;--grid-header-padding-y: 14px;--grid-header-padding-x: 12px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 12px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-strong);--grid-divider-width: 1px;--grid-radius-outer: 2px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=financial]{--grid-header-bg: var(--grid-surface-container);--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 500;--grid-header-text-transform: uppercase;--grid-header-letter-spacing: .08em;--grid-header-font-size: 11px;--grid-header-padding-y: 12px;--grid-header-padding-x: 14px;--grid-cell-padding-y: 10px;--grid-cell-padding-x: 14px;--grid-zebra-odd: transparent;--grid-zebra-even: var(--grid-tint-subtle);--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-font-feature-numeric: \"tnum\"}eru-grid[data-preset=elevated]{--grid-header-bg: transparent;--grid-header-color: var(--grid-on-surface-variant);--grid-header-font-weight: 600;--grid-header-text-transform: none;--grid-header-font-size: 12px;--grid-header-padding-y: 16px;--grid-header-padding-x: 18px;--grid-cell-padding-y: 14px;--grid-cell-padding-x: 18px;--grid-row-hover: var(--grid-tint-soft);--grid-divider-color: var(--grid-tint-subtle);--grid-divider-width: 1px;--grid-radius-outer: 16px;--grid-shadow-outer: 0 1px 3px rgba(0, 0, 0, .06), 0 10px 28px rgba(0, 0, 0, .07);--grid-font-feature-numeric: \"tnum\";--grid-pill-padding-y: 4px;--grid-pill-padding-x: 12px;overflow:hidden}.group-container{padding-bottom:8px}.column-header.design-clickable .design-edit-icon{font-size:16px;width:16px;height:16px;margin-left:4px;opacity:.45;vertical-align:middle;cursor:pointer}.column-header.design-clickable:hover .design-edit-icon,.column-header.design-clickable .design-edit-icon:hover{opacity:1}.column-header.design-selected{background-color:var(--grid-primary-light, rgba(63, 81, 181, .12))}.pivot-column-header .pivot-header-content{display:flex;align-items:center;justify-content:center;gap:4px;min-width:0}.pivot-column-header .pivot-header-content .pivot-header-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.pivot-column-header .pivot-header-content .design-edit-icon,.pivot-column-header .header-content .design-edit-icon{flex:0 0 auto}.pivot-column-header .header-content data-cell,.pivot-column-header .header-content data-cell *{color:inherit!important}.incremental-row-container{width:100%;height:100%;min-height:var(--grid-min-height, 120px);max-height:none;overflow:auto;position:relative;background-color:var(--grid-surface);border-radius:var(--grid-border-radius);font-family:var(--grid-font-family)}.viewport{height:100%;min-height:300px;overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface);scrollbar-gutter:stable}.viewport.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.groups-viewport{height:100%;min-height:300px}.groups-scroll-container{max-height:var(--grid-height, 600px);overflow-y:auto;overflow-x:hidden}.table-viewport{background-color:var(--grid-surface);height:var(--table-height, auto);min-height:var(--table-min-height, 100px);overflow-x:auto;overflow-y:auto}.pivot-viewport{min-height:var(--table-min-height, 300px);overflow-x:auto;overflow-y:auto;background-color:var(--grid-surface)}.pivot-viewport .cdk-virtual-scroll-content-wrapper{width:auto;height:auto}.table-wrapper{min-width:100%;overflow-x:visible}.incremental-row-container .eru-grid-table,.eru-grid-table{width:100%!important;border-collapse:separate;border-spacing:0;table-layout:fixed!important;background-color:var(--grid-surface);color:var(--grid-on-surface);font-family:var(--grid-font-family);font-size:var(--grid-font-size-body);line-height:var(--grid-line-height-body)}.eru-grid-table th,.eru-grid-table td{text-align:left;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;color:var(--grid-on-surface);min-width:0;max-width:100%!important;box-sizing:border-box;position:relative}.eru-grid-table th{background-color:var(--grid-header-bg, var(--grid-surface-container))}thead.eru-wrap-headers th{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;height:auto}thead.eru-wrap-headers th .column-label,thead.eru-wrap-headers th .header-label{white-space:normal!important;overflow:visible!important;text-overflow:clip!important;word-break:break-word;overflow-wrap:anywhere}.eru-grid-table tbody td{background-color:transparent}.eru-grid-table thead{background-color:var(--grid-header-bg, var(--grid-surface-container));transform:translateZ(0);will-change:transform;backface-visibility:hidden}.eru-grid-table thead.freeze-header-enabled{position:sticky!important;top:0!important;z-index:100!important}.eru-grid-table thead th{background-color:var(--grid-header-bg, var(--grid-surface-container));color:var(--grid-header-color, var(--grid-on-surface));font-family:var(--grid-font-family);font-weight:var(--grid-header-font-weight);font-size:var(--grid-header-font-size)}.checkbox-column{width:50px;min-width:50px;max-width:50px;text-align:center;background-color:var(--grid-surface-container)}.checkbox-column input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:var(--grid-primary);border-radius:var(--grid-border-radius)}.checkbox-column input[type=checkbox]:focus{outline:2px solid var(--grid-primary);outline-offset:2px}.action-column{text-align:center;background-color:var(--grid-surface-container)}.action-column mat-icon{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--grid-on-surface-variant);cursor:pointer}.action-column mat-icon:hover{color:var(--grid-primary)}.action-column .action-icons{display:flex;align-items:center;justify-content:center;gap:6px;overflow-x:auto;scrollbar-width:none}.action-column .action-icons::-webkit-scrollbar{display:none}.action-column .action-icon{flex:0 0 auto}.eru-grid-action-menu .mat-mdc-menu-item mat-icon{margin-right:8px;font-size:18px;width:18px;height:18px;line-height:18px;color:var(--grid-on-surface-variant)}.group-header{background-color:var(--grid-surface-container);color:var(--grid-on-surface);font-size:var(--grid-font-size-caption);font-weight:500;border-bottom:1px solid var(--grid-outline);cursor:pointer;transition:background-color .2s ease}.group-header:hover{background-color:var(--grid-surface-container-high)}.group-header .group-title{font-weight:600;color:var(--grid-primary)}.group-header .group-row-count{color:var(--grid-on-surface-variant);font-size:var(--grid-font-size-caption);margin-left:var(--grid-spacing-sm)}.row-item{background-color:var(--grid-surface);transition:background-color .15s ease}.row-item:nth-child(odd){background-color:var(--grid-zebra-odd, var(--grid-surface))}.row-item:nth-child(2n){background-color:var(--grid-zebra-even, var(--grid-surface))}.row-item:hover{background-color:var(--grid-row-hover)}.required-toggle-row{background-color:var(--grid-surface-container, #f3edf7);border-bottom:1px solid var(--grid-outline-variant, #cac4d0)}.required-toggle-row .required-toggle-cell{padding:4px 8px!important;text-align:center;vertical-align:middle;position:relative}.required-toggle-row .required-toggle-cell .required-label{position:absolute;top:2px;left:4px;font-size:10px;color:var(--grid-on-surface-variant, #49454f);font-weight:400;text-transform:lowercase}.required-toggle-row .required-toggle-cell mat-checkbox{display:flex;justify-content:center;align-items:center}.table-column-header{padding:var(--grid-header-padding-y) var(--grid-header-padding-x)}.column-header{font-weight:var(--grid-header-font-weight);text-transform:var(--grid-header-text-transform);letter-spacing:var(--grid-header-letter-spacing);text-align:center!important;font-size:var(--grid-header-font-size);position:relative;-webkit-user-select:none;user-select:none;background-color:var(--grid-header-bg, var(--grid-surface-container));color:var(--grid-header-color, var(--grid-on-surface))}.column-header:hover{background-color:var(--grid-header-hover-bg, var(--grid-surface-container-high))}.column-drag-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:grab;opacity:0;transition:opacity .2s ease,background-color .2s ease;z-index:2;display:flex;align-items:center;justify-content:center;border-right:1px solid transparent}.column-drag-handle:after{content:\"\\22ee\\22ee\";font-size:14px;color:var(--grid-on-surface-variant);transform:rotate(90deg)}.column-drag-handle:hover{background-color:var(--grid-surface-container-high);border-right-color:var(--grid-outline)}.column-header:hover .column-drag-handle{opacity:1}.column-drag-handle:active{cursor:grabbing}.sortable-header{cursor:pointer}.sortable-header .column-label{flex:1}.sortable-header .sort-indicator{display:inline-flex;align-items:center;gap:2px;margin-left:4px;cursor:pointer;vertical-align:middle;opacity:0;transition:opacity .15s ease}.sortable-header .sort-indicator .sort-triangles{display:flex;flex-direction:column;align-items:center;gap:2px}.sortable-header .sort-indicator .sort-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;cursor:pointer;transition:border-color .15s ease}.sortable-header .sort-indicator .sort-tri-up{border-bottom:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.sortable-header .sort-indicator .sort-tri-down{border-top:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.sortable-header .sort-indicator .sort-tri-active{opacity:1}.sortable-header .sort-indicator .sort-tri-active.sort-tri-up{border-bottom-color:var(--grid-primary, #6750a4)}.sortable-header .sort-indicator .sort-tri-active.sort-tri-down{border-top-color:var(--grid-primary, #6750a4)}.sortable-header .sort-indicator .sort-priority{font-size:9px;font-weight:600;color:var(--grid-primary, #6750a4);line-height:1;min-width:12px;text-align:center}.sortable-header:hover .sort-indicator,.sortable-header.sort-asc .sort-indicator,.sortable-header.sort-desc .sort-indicator{opacity:1}.sortable-header:hover .sort-indicator .sort-tri:not(.sort-tri-active){opacity:.6}.sort-asc,.sort-desc{background-color:var(--grid-surface-container-low, rgba(103, 80, 164, .04))}.dragging{opacity:1;background-color:var(--grid-surface-container);box-shadow:var(--grid-elevation-2)}.drag-over{background-color:var(--grid-surface-container);border-color:var(--grid-primary)}.data-cell{background-color:transparent;color:var(--grid-on-surface);font-family:var(--grid-font-family);font-size:var(--grid-font-size-body);font-feature-settings:var(--grid-font-feature-numeric);padding:var(--grid-cell-padding-y) var(--grid-cell-padding-x)}.cell-content{align-items:center}.cell-content .mdc-text-field{padding:0px var(--grid-spacing-xxs)!important}.cell-display-text{align-items:center;padding:0px var(--grid-spacing-xs)}.ghost-loading-row{background-color:transparent}.ghost-cell-container{padding:var(--grid-spacing-sm)}.ghost-cell{height:20px;width:100%;background-color:var(--grid-surface-container);animation:pulse 1.5s ease-in-out infinite;border-radius:var(--grid-border-radius)}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.column-resizer{position:absolute;right:0;top:0;bottom:0;width:4px;cursor:col-resize;background-color:transparent;transition:background-color .2s ease}.column-resizer:hover{background-color:var(--grid-primary)}.group-separator{height:var(--grid-spacing-sm);background-color:var(--grid-surface-variant)}.group-separator .separator-cell{background-color:var(--grid-surface-variant);border:none;height:var(--grid-spacing-sm)}.error-state{background-color:var(--grid-error-container);color:var(--grid-error);border-color:var(--grid-error)}.error-message{background-color:var(--grid-error);color:#fff;padding:var(--grid-spacing-sm);border-radius:var(--grid-border-radius);font-size:var(--grid-font-size-caption)}.incremental-row-container .eru-grid-table tbody,.incremental-row-container .eru-grid-table{position:relative}.incremental-row-container .eru-grid-table.show-column-lines{border-right:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important;border-top:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table.show-column-lines:not(.freeze-header){border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table:not(.show-column-lines){border:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.incremental-row-container .eru-grid-table thead:after{content:\"\";position:absolute;bottom:0;left:0;right:0;height:calc(var(--grid-divider-width, 1px) * 2);background-color:var(--grid-divider-color, var(--grid-outline, #e0e0e0));pointer-events:none;z-index:10}.incremental-row-container .eru-grid-table.show-column-lines thead th,.incremental-row-container .eru-grid-table.show-column-lines tbody td{border-left:var(--grid-divider-width, 1px) solid var(--grid-divider-color, var(--grid-outline, #e0e0e0))!important}.incremental-row-container .eru-grid-table.show-row-lines thead th,.incremental-row-container .eru-grid-table.show-row-lines tbody td{border-bottom:var(--grid-divider-width, 1px) solid var(--grid-divider-color, var(--grid-outline, #e0e0e0))!important}@media(max-width:768px){.incremental-row-container{height:600px}.eru-grid-table th,.eru-grid-table td{font-size:var(--grid-font-size-caption)}.checkbox-column{width:40px;min-width:40px;max-width:40px}}@media(prefers-contrast:high){.eru-grid-table th,.eru-grid-table td{border-width:2px}.row-item:hover{border-width:2px;border-color:var(--grid-primary)}}@media(prefers-reduced-motion:reduce){.row-item,.column-drag-handle,.ghost-cell{transition:none;animation:none}}.pivot-table .nested-header{text-align:center;font-weight:600;background:var(--grid-surface-container)}.pivot-table .nested-header.row-dimension-header{background:var(--grid-surface-container);font-weight:600}.pivot-table .pivot-header-leafcols{padding:0;margin:0;height:0}.pivot-table .pivot-header-level.level-0 .nested-header{font-size:14px;padding:12px 8px}.pivot-table .pivot-header-level.level-1 .nested-header{font-size:13px;padding:10px 6px}.pivot-table .pivot-header-level.level-2 .nested-header{font-size:12px;padding:8px 4px}.pivot-table .nested-header:hover{background:var(--grid-surface-variant);color:var(--grid-primary);transition:all .2s ease}.pivot-table .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-table .pivot-cell-content{display:flex;justify-content:center;align-items:center;min-height:38px}.pivot-table .pivot-repeated-value .cell-content,.pivot-table .pivot-repeated-value .pivot-cell-content{visibility:hidden}.pivot-table .pivot-group-start.row-dimension-cell{border-top:1px solid var(--grid-outline, #79757f)}.pivot-mode .incremental-row-container{display:flex;flex-direction:column;height:auto;max-height:85vh;overflow:auto}.pivot-mode .h-shell{position:relative;width:calc(100% - var(--scrollbar-width, 17px))!important;top:0;z-index:1;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .h-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell{position:relative;bottom:50px;flex-shrink:0;overflow-x:hidden;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .gt-shell::-webkit-scrollbar{display:none}.pivot-mode .gt-shell table{border-bottom:var(--grid-outline-width, 1px) solid var(--grid-outline, #e0e0e0)!important}.pivot-mode .gt-shell.adjust-bottom-vs{bottom:66px!important}.pivot-mode .gt-shell.adjust-bottom:not(.adjust-bottom-vs){bottom:calc(66px - var(--scrollbar-width, 17px))!important}.pivot-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.pivot-mode .header-shell::-webkit-scrollbar{display:none}.pivot-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.pivot-mode .header-shell .eru-grid-table{margin-bottom:0;width:100%;table-layout:fixed}.pivot-mode .header-shell .eru-grid-table thead{background:var(--grid-surface-container)}.pivot-mode .header-shell .eru-grid-table thead th{background:var(--grid-surface-container);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .header-shell .eru-grid-table thead th.sticky-column{position:sticky;background:var(--grid-surface-container);z-index:111}.pivot-mode .header-shell .eru-grid-table tbody td{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-container{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden}.pivot-mode .pivot-table{width:auto!important;min-width:100%!important;table-layout:fixed!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important}.pivot-mode .pivot-table td,.pivot-mode .pivot-table th{box-sizing:border-box!important;flex:none!important;flex-shrink:0!important;flex-grow:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-table{table-layout:fixed!important;width:100%!important}.pivot-mode .pivot-table *{max-width:var(--col-width)!important;box-sizing:border-box!important}.pivot-mode .pivot-table colgroup{width:100%!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex-basis:var(--col-width)!important;flex:0 0 var(--col-width)!important}.pivot-mode .pivot-table table{width:100%!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important}.pivot-mode .pivot-table[style*=--table-total-width]{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important}.pivot-mode .pivot-table colgroup col{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;flex:0 0 var(--col-width)!important;flex-basis:var(--col-width)!important;flex-grow:0!important;flex-shrink:0!important;overflow:hidden!important}.pivot-mode .pivot-table tbody td,.pivot-mode .pivot-table thead th{width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important}.pivot-mode .pivot-table .cell-content,.pivot-mode .pivot-table data-cell{width:100%!important;max-width:100%!important;overflow:hidden!important;text-overflow:ellipsis!important;white-space:nowrap!important;display:block!important}.pivot-mode .pivot-table table{width:var(--table-total-width)!important;min-width:var(--table-total-width)!important;max-width:var(--table-total-width)!important;table-layout:fixed!important;border-collapse:collapse!important;border-spacing:0!important;word-wrap:break-word!important;word-break:break-all!important}.pivot-mode .pivot-tbody tr.pivot-row{min-height:var(--grid-data-row-height, 50px)!important;height:var(--grid-data-row-height, 50px)!important}.pivot-mode .pivot-tbody tr.pivot-row:hover{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-tbody tr.pivot-row:nth-child(2n){background-color:#00000005}.pivot-mode .pivot-tbody tr.pivot-row td{min-height:var(--grid-data-row-height, 50px)!important;height:var(--grid-data-row-height, 50px)!important;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content{min-height:calc(var(--grid-data-row-height, 50px) - 2px);display:flex;align-items:center;justify-content:center}.pivot-mode .pivot-tbody tr.pivot-row td .cell-content data-cell{width:100%;min-height:calc(var(--grid-data-row-height, 50px) - 4px);display:flex;align-items:center;justify-content:center;overflow:hidden;flex-shrink:0}.pivot-mode .pivot-cell{vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;width:var(--col-width)!important;min-width:var(--col-width)!important;max-width:var(--col-width)!important}.pivot-mode .pivot-cell.aggregated-value{font-weight:500;font-family:Roboto Mono,monospace}.pivot-mode .pivot-cell .cell-content{display:flex;justify-content:center;align-items:center;min-height:var(--grid-header-row-height, 40px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:0}.pivot-mode .pivot-table .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.pivot-mode .pivot-table .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .subtotal-row td:first-child{color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row td.aggregated-value{font-weight:500;color:var(--grid-primary)}.pivot-mode .pivot-table .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.pivot-mode .pivot-table .subtotal-bold td{font-weight:600!important;font-style:normal!important}.pivot-mode .pivot-table .subtotal-bold td.aggregated-value{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td{font-style:italic!important}.pivot-mode .pivot-table .subtotal-italic td:first-child{font-weight:600!important}.pivot-mode .pivot-table .subtotal-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.pivot-mode .pivot-table .subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted td.aggregated-value{font-weight:500!important;color:var(--grid-primary)!important}.pivot-mode .pivot-table .subtotal-highlighted:hover,.pivot-mode .pivot-table .subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-row{background-color:var(--grid-surface-container-high)!important;font-weight:700;font-size:var(--grid-font-size-body)}.pivot-mode .pivot-table .grand-total-row td{background-color:var(--grid-surface-container-high)!important;color:var(--grid-on-surface)}.pivot-mode .pivot-table .grand-total-row td:first-child{font-style:normal;font-weight:800;color:var(--grid-primary)}.pivot-mode .pivot-table .grand-total-row td.aggregated-value{font-weight:500;color:var(--grid-primary);font-family:Roboto Mono,monospace}.pivot-mode .pivot-table .grand-total-row:hover,.pivot-mode .pivot-table .grand-total-row:hover td{background-color:var(--grid-surface-container-high)!important}.pivot-mode .pivot-table .grand-total-bold td{font-weight:700!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-bold td.aggregated-value{font-weight:700!important}.pivot-mode .pivot-table .grand-total-italic td,.pivot-mode .pivot-table .grand-total-italic td.aggregated-value{font-style:italic!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted{background-color:var(--grid-primary)!important;box-shadow:var(--grid-elevation-2)!important}.pivot-mode .pivot-table .grand-total-highlighted td{background-color:var(--grid-primary)!important;color:var(--grid-on-primary)!important;font-weight:500!important;font-style:normal!important}.pivot-mode .pivot-table .grand-total-highlighted td.aggregated-value{color:var(--grid-on-primary)!important;font-weight:500!important}.pivot-mode .pivot-table .grand-total-highlighted:hover,.pivot-mode .pivot-table .grand-total-highlighted:hover td{background-color:var(--grid-primary)!important}.pivot-mode .pivot-table .collapsible-header{position:relative}.pivot-mode .pivot-table .collapsible-header .header-content{display:flex;align-items:center;justify-content:space-between;gap:var(--grid-spacing-xs);padding:var(--grid-spacing-xs) var(--grid-spacing-sm)}.pivot-mode .pivot-table .collapsible-header .header-label{flex:1;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn{background:none;border:none;cursor:pointer;padding:var(--grid-spacing-xxs);margin:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:var(--grid-border-radius);color:var(--grid-on-surface-variant);transition:all .2s ease;font-size:12px;font-weight:600}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:hover{background-color:var(--grid-surface-container);color:var(--grid-primary);transform:scale(1.1)}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn:focus{outline:2px solid var(--grid-primary);outline-offset:1px}.pivot-mode .pivot-table .collapsible-header .collapse-toggle-btn .collapse-icon{display:block;line-height:1;font-family:monospace;font-size:14px}.pivot-mode .pivot-table .collapsible-header.expanded .collapse-toggle-btn .collapse-icon{color:var(--grid-primary)}.pivot-mode .pivot-table .collapsible-header.collapsed{background-color:var(--grid-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .header-label{font-style:italic;color:var(--grid-on-surface-variant)}.pivot-mode .pivot-table .collapsible-header.collapsed .collapse-toggle-btn .collapse-icon{color:var(--grid-outline)}.pivot-mode .pivot-table .collapsible-header:hover{background-color:var(--grid-surface-container)}.pivot-mode .pivot-table .collapsible-header:hover .header-label{color:var(--grid-on-surface)}.pivot-mode .pivot-table .pivot-single-table{display:flex;flex-direction:column;height:100%;width:100%;overflow:hidden;min-height:var(--table-min-height)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container{flex-shrink:0;background:var(--grid-surface)!important;overflow-x:auto;overflow-y:hidden;min-height:100px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table{width:auto;min-width:100%;height:auto!important;min-height:100px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th{background:var(--grid-surface-container)!important;padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:40px!important;height:auto!important;position:relative;visibility:visible!important;color:var(--grid-on-surface)!important}.pivot-mode .pivot-table .pivot-single-table .pivot-header-container .pivot-table th.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:101!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container{flex:1;overflow:auto;min-height:300px!important;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-viewport{height:100%!important;width:100%!important;overflow-x:auto!important;overflow-y:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table{width:auto;min-width:100%;height:auto!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td{padding:8px 6px!important;white-space:nowrap;min-width:50px;min-height:32px!important;height:auto!important;background:var(--grid-surface)!important;color:var(--grid-on-surface)!important;visibility:visible!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table td.sticky-column,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table td.sticky-column{position:sticky!important;background:var(--grid-surface-container)!important;border-right:2px solid var(--grid-primary)!important;box-shadow:2px 0 4px #0000001a;z-index:100!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr{height:auto!important;min-height:50px!important}.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-table tbody tr.pivot-row,.pivot-mode .pivot-table .pivot-single-table .pivot-data-container .pivot-data-table tbody tr.pivot-row{visibility:visible!important;display:table-row!important}.pivot-mode .pivot-table .collapsed-column-group{background-color:var(--grid-surface-container);border-left:3px solid var(--grid-primary)}.pivot-mode .pivot-table .collapsed-column-group:hover{background-color:var(--grid-surface-container-high)}.pivot-row.subtotal-row{background-color:var(--grid-surface-variant);font-weight:500}.pivot-row.subtotal-row.subtotal-bold{font-weight:500}.pivot-row.subtotal-row.subtotal-italic{font-style:italic}.pivot-row.subtotal-row.subtotal-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.grand-total-row{background-color:var(--grid-surface-container);font-weight:600}.pivot-row.grand-total-row.grand-total-bold{font-weight:800}.pivot-row.grand-total-row.grand-total-italic{font-style:italic}.pivot-row.grand-total-row.grand-total-highlighted{background-color:var(--grid-primary);color:var(--grid-on-primary)}.pivot-row.first-visible-row{background-color:#6750a41a!important;position:relative}.pivot-row.first-visible-row:before{content:\"\\1f441\\fe0f First Visible\";position:absolute;top:-20px;left:0;background:var(--grid-primary);color:var(--grid-on-primary);padding:2px 6px;font-size:10px;border-radius:2px;z-index:1000}.header-wrap-text{white-space:pre-wrap;word-break:auto-phrase}.group-header-row{display:flex;align-items:center;justify-content:space-between;width:100%;padding-right:12px}.custom-collapse-header{background-color:var(--grid-surface-variant);padding:8px 20px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:pointer;display:flex;width:fit-content;align-items:center;-webkit-user-select:none;user-select:none;min-width:200px;margin-bottom:10px;position:sticky;left:1px;z-index:116}.custom-collapse-header .collapse-arrow{display:inline-block;margin-right:8px;font-size:12px;color:var(--grid-on-surface-variant);transition:transform .2s ease;transform:rotate(0)}.custom-collapse-header .collapse-arrow.rotate-arrow{transform:rotate(270deg)}.custom-collapse-header .f-12{font-size:12px;color:var(--grid-on-surface)}.custom-collapse-header .group-sort-indicator{display:inline-flex;align-items:center;margin-left:8px}.custom-collapse-header .group-sort-indicator .sort-triangles{display:flex;flex-direction:column;align-items:center;gap:2px}.custom-collapse-header .group-sort-indicator .sort-tri{width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;cursor:pointer;transition:border-color .15s ease}.custom-collapse-header .group-sort-indicator .sort-tri-up{border-bottom:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.custom-collapse-header .group-sort-indicator .sort-tri-down{border-top:5px solid var(--grid-on-surface-variant, #49454f);opacity:.3}.custom-collapse-header .group-sort-indicator .sort-tri-active{opacity:1}.custom-collapse-header .group-sort-indicator .sort-tri-active.sort-tri-up{border-bottom-color:var(--grid-primary, #6750a4)}.custom-collapse-header .group-sort-indicator .sort-tri-active.sort-tri-down{border-top-color:var(--grid-primary, #6750a4)}.excel-download-icon{cursor:pointer}.excel-download-icon:hover{opacity:.75}.excel-download-bar{display:flex;justify-content:flex-end;padding:4px 12px}.table-mode .header-shell{flex-shrink:0;width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.table-mode .header-shell::-webkit-scrollbar{display:none}.table-mode .header-shell.apply-cdk-width{width:calc(var(--table-total-width) + 10px)!important}.table-mode .subtotal-row{background-color:var(--grid-surface-container)!important;font-weight:600}.table-mode .subtotal-row td{background-color:var(--grid-surface-container);color:var(--grid-on-surface-variant)}.table-mode .subtotal-row td:first-child{color:var(--grid-primary)}.table-mode .subtotal-row td.subtotal-cell{font-weight:500}.table-mode .subtotal-row td.subtotal-cell .subtotal-label{font-weight:600;color:var(--grid-primary)}.table-mode .subtotal-row:hover{background-color:var(--grid-surface-container-high)!important}.table-mode .subtotal-row:hover td{background-color:var(--grid-surface-container-high)}.table-mode .subtotal-row.subtotal-bold td{font-weight:600!important;font-style:normal!important}.table-mode .subtotal-row.subtotal-italic td{font-style:italic!important}.table-mode .subtotal-row.subtotal-italic td:first-child{font-weight:600!important}.table-mode .subtotal-row.subtotal-highlighted{background-color:var(--grid-surface-variant)!important}.table-mode .subtotal-row.subtotal-highlighted td{background-color:var(--grid-surface-variant)!important;font-weight:700!important;font-style:normal!important;color:var(--grid-primary)!important}.table-mode .subtotal-row.subtotal-highlighted:hover,.table-mode .subtotal-row.subtotal-highlighted:hover td{background-color:var(--grid-surface-container-high)!important}.table-mode .subtotal-row-shell{width:100%;box-sizing:border-box;padding-right:var(--scrollbar-width, 17px);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.table-mode .subtotal-row-shell::-webkit-scrollbar{display:none}.board-mode-host{overflow:hidden;display:flex;flex-direction:column;max-height:var(--grid-height, 600px)}.board-mode-host .board-view-container{display:flex;flex-direction:column;flex:1;min-height:0}.board-mode-host .board-sort-bar{display:flex;align-items:center;gap:6px;padding:8px 16px;flex-shrink:0;border-bottom:1px solid var(--grid-outline-variant, #cac4d0);background:var(--grid-surface, #fffbfe);overflow-x:auto}.board-mode-host .board-sort-bar .board-sort-label{font-size:12px;font-weight:500;color:var(--grid-on-surface-variant, #49454f);white-space:nowrap}.board-mode-host .board-sort-bar .board-sort-chip{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:16px;border:1px solid var(--grid-outline-variant, #cac4d0);background:var(--grid-surface, #fffbfe);color:var(--grid-on-surface, #1d1b20);font-size:12px;white-space:nowrap}.board-mode-host .board-sort-bar .board-sort-chip-active{background:var(--grid-surface-container);border-color:var(--grid-outline, #79757f);color:var(--grid-on-surface, #1d1b20)}.board-mode-host .board-sort-bar .board-sort-chip-label{pointer-events:none}.board-mode-host .board-sort-bar .board-sort-chip-arrow{font-size:10px;line-height:1;cursor:pointer;padding:2px;border-radius:4px}.board-mode-host .board-sort-bar .board-sort-chip-arrow:hover{background:#00000014}.board-mode-host .board-sort-bar .board-sort-chip-priority{font-size:9px;font-weight:700;background:var(--grid-primary, #6750a4);color:var(--grid-on-primary, #ffffff);border-radius:50%;width:14px;height:14px;display:inline-flex;align-items:center;justify-content:center}.board-mode-host .board-sort-bar .board-sort-chip-remove{font-size:10px;cursor:pointer;padding:2px;border-radius:4px;color:var(--grid-on-surface-variant, #49454f)}.board-mode-host .board-sort-bar .board-sort-chip-remove:hover{background:#00000014;color:var(--grid-error, #b3261e)}.board-mode-host .board-sort-bar .board-sort-add-btn{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:16px;border:1px dashed var(--grid-outline-variant, #cac4d0);background:transparent;color:var(--grid-on-surface-variant, #49454f);font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s ease,border-color .15s ease}.board-mode-host .board-sort-bar .board-sort-add-btn .board-sort-add-icon{font-size:14px;width:14px;height:14px}.board-mode-host .board-sort-bar .board-sort-add-btn:hover{background:var(--grid-surface-container-low, #f7f2fa);border-color:var(--grid-primary, #6750a4);color:var(--grid-primary, #6750a4)}.board-mode-host .board-sort-bar .board-sort-clear{display:inline-flex;align-items:center;padding:4px 10px;border-radius:16px;border:1px solid var(--grid-error, #b3261e);background:transparent;color:var(--grid-error, #b3261e);font-size:12px;cursor:pointer;white-space:nowrap;transition:background .15s ease}.board-mode-host .board-sort-bar .board-sort-clear:hover{background:#b3261e14}.board-mode-host .board-columns-wrapper{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--board-col-min-width, 300px),var(--board-col-max-width, 1fr)));grid-auto-rows:auto;align-items:start;gap:16px;flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;align-content:start;justify-content:start}.board-mode-host .board-columns-wrapper.board-columns-nowrap{grid-auto-flow:column;grid-template-columns:none;grid-template-rows:auto;grid-auto-rows:auto;grid-auto-columns:minmax(var(--board-col-min-width, 300px),var(--board-col-max-width, 1fr));overflow-x:auto;overflow-y:hidden}.board-mode-host .board-column{max-height:var(--board-column-height, 420px);min-width:0;display:flex;flex-direction:column;background:var(--grid-surface-container, #f3edf7);border-radius:12px;min-height:0;overflow:hidden}.board-mode-host .board-column.board-column-accented{border-top:3px solid var(--board-group-color, transparent)}.board-mode-host .board-column .column-header{display:flex;align-items:center;justify-content:space-between;gap:8px;padding:10px 14px;font-weight:600;flex-shrink:0}.board-mode-host .board-column .column-header:hover{background-color:transparent}.board-mode-host .board-column .column-header .column-header-title{font-size:15px;font-weight:700;letter-spacing:.2px;line-height:1.2;color:var(--grid-on-surface, #1d1b20);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.board-mode-host .board-column .column-header .column-header-title-cell{display:inline-flex;align-items:center;flex:1 1 auto;min-width:0;overflow:visible;text-overflow:clip}.board-mode-host .board-column .column-header .column-header-title-cell data-cell,.board-mode-host .board-column .column-header .column-header-title-cell .data-cell-component,.board-mode-host .board-column .column-header .column-header-title-cell .container{padding:0!important;margin:0!important;border:none!important;background:transparent!important;min-height:0!important;height:auto!important;width:auto!important;max-width:100%!important;overflow:visible!important}.board-mode-host .board-column .column-header .column-header-title-cell .status-display,.board-mode-host .board-column .column-header .column-header-title-cell .status-display-content,.board-mode-host .board-column .column-header .column-header-title-cell .status-text,.board-mode-host .board-column .column-header .column-header-title-cell .tag-display,.board-mode-host .board-column .column-header .column-header-title-cell .tag-text{max-width:none!important;overflow:visible!important;text-overflow:clip!important}.board-mode-host .board-column .column-header .column-header-count{font-size:10px;font-weight:600;color:var(--eru-board-count-color, var(--grid-on-surface-variant, #49454f));background:var(--eru-board-count-bg, var(--grid-surface-variant, #e7e0ec));border-radius:10px;padding:3px 10px;white-space:nowrap;flex-shrink:0}.board-mode-host .board-column-body{flex:0 1 auto;min-height:0}.board-mode-host .board-card-container{box-sizing:border-box;overflow:hidden;border-radius:8px;transition:background-color .15s ease,box-shadow .15s ease}.board-mode-host .board-card-container.show-row-lines{box-shadow:inset 0 0 0 var(--grid-divider-width, 1px) var(--grid-divider-color, var(--grid-outline, #e0e0e0))}.board-mode-host .board-card-container:hover{background-color:var(--eru-board-card-hover-bg, color-mix(in srgb, var(--mat-sys-primary, #1976d2) 8%, transparent))}.board-mode-host .board-card-container.selected{background-color:var(--eru-board-card-selected-bg, color-mix(in srgb, var(--mat-sys-primary, #1976d2) 14%, transparent));box-shadow:inset 0 0 0 2px var(--eru-board-card-selected-outline, var(--mat-sys-primary, #1976d2))}.board-mode-host .board-card{height:calc(100% - 8px);overflow:hidden;cursor:pointer}.board-mode-host .board-card mat-card-title{font-size:13px}.board-mode-host .board-card mat-card-subtitle{font-size:12px}.board-mode-host .board-card-field{display:flex;flex-direction:column;margin-bottom:4px}.board-mode-host .board-field-label{font-size:10px;color:var(--grid-on-surface-variant, #49454f);font-weight:500;text-transform:uppercase;letter-spacing:.5px}.board-mode-host .board-ghost-card{margin:8px;padding:16px;background:var(--grid-surface, #fef7ff);border-radius:8px;animation:board-pulse 1.5s ease-in-out infinite}.board-mode-host .board-ghost-line{height:12px;background:var(--grid-surface-variant, #e7e0ec);border-radius:4px;margin-bottom:8px}.board-mode-host .board-ghost-line--short{width:60%}@keyframes board-pulse{0%,to{opacity:1}50%{opacity:.5}}th.row-expand-toggle,td.row-expand-toggle{width:40px!important;min-width:40px!important;max-width:40px!important;padding:0!important;text-align:center;vertical-align:middle;cursor:pointer;-webkit-user-select:none;user-select:none;box-sizing:border-box}.row-expand-icon{font-size:20px;width:20px;height:20px;line-height:20px;color:var(--grid-on-surface-variant);transition:transform .15s ease-in-out}.row-expand-icon.expanded{transform:rotate(90deg)}.row-detail{background:var(--grid-surface-container)}.row-detail .row-detail-cell{padding:var(--grid-spacing-sm) var(--grid-spacing-md);border-bottom:1px solid var(--grid-outline-variant)}.row-detail .row-detail-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:var(--grid-spacing-sm) var(--grid-spacing-md)}.row-detail .row-detail-field{display:flex;flex-direction:column;gap:var(--grid-spacing-xxs);min-width:0}.row-detail .row-detail-label{font-size:var(--grid-font-size-caption);color:var(--grid-on-surface-variant);font-weight:500}.row-detail .row-detail-value{min-width:0}.row-detail .row-detail-value data-cell{display:block;width:100%}\n"] }]
|
|
14584
14645
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { allViewports: [{
|
|
14585
14646
|
type: ViewChildren,
|
|
14586
14647
|
args: [CdkVirtualScrollViewport]
|
|
@@ -14676,7 +14737,7 @@ class ThemeToggleComponent {
|
|
|
14676
14737
|
</button>
|
|
14677
14738
|
}
|
|
14678
14739
|
</mat-menu>
|
|
14679
|
-
`, isInline: true, styles: [".theme-toggle-button{color:var(--grid-on-surface)}.theme-toggle-button:hover{background-color:var(--grid-surface-variant)}.active{background-color:var(--grid-primary-light);color:var(--grid-primary-color)}.check-icon{margin-left:auto;color:var(--grid-primary-color)}mat-menu-item{display:flex;align-items:center;gap:8px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$
|
|
14740
|
+
`, isInline: true, styles: [".theme-toggle-button{color:var(--grid-on-surface)}.theme-toggle-button:hover{background-color:var(--grid-surface-variant)}.active{background-color:var(--grid-primary-light);color:var(--grid-primary-color)}.check-icon{margin-left:auto;color:var(--grid-primary-color)}mat-menu-item{display:flex;align-items:center;gap:8px}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i7.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: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14680
14741
|
}
|
|
14681
14742
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: ThemeToggleComponent, decorators: [{
|
|
14682
14743
|
type: Component,
|
|
@@ -14720,5 +14781,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
14720
14781
|
* Generated bundle index. Do not edit.
|
|
14721
14782
|
*/
|
|
14722
14783
|
|
|
14723
|
-
export { AttachmentComponent, CheckboxComponent, ColumnConstraintsService, CurrencyComponent, CustomVirtualScrollStrategy, DATA_TYPES, DATETIME_FORMATS, DATE_FORMATS, DateComponent, DatetimeComponent, DurationComponent, EmailComponent, EruGridComponent, EruGridService, EruGridStore, INHERITED_FIELD_KEYS, LocationComponent, MATERIAL_MODULES, MATERIAL_PROVIDERS, MONTH_SHORT_NAMES, NumberComponent, PRESET_CONFIG_DEFAULTS, PRESET_MANAGED_FIELDS, PeopleComponent, PhoneComponent, PriorityComponent, ProgressComponent, RatingComponent, SelectComponent, StatusComponent, TagComponent, TextareaComponent, TextboxComponent, ThemeService, ThemeToggleComponent, WebsiteComponent, evaluateRowCondition, formatDateWithPattern, matchColorRange, normalizeDatatype, normalizeDateFormat, normalizeDateTimeFormat, parseDateWithPattern, resolveRowValue };
|
|
14784
|
+
export { AttachmentComponent, CheckboxComponent, ColumnConstraintsService, CurrencyComponent, CustomVirtualScrollStrategy, DATA_TYPES, DATETIME_FORMATS, DATE_FORMATS, DateComponent, DatetimeComponent, DurationComponent, EmailComponent, EruGridComponent, EruGridService, EruGridStore, INHERITED_FIELD_KEYS, LocationComponent, MATERIAL_MODULES, MATERIAL_PROVIDERS, MONTH_SHORT_NAMES, NumberComponent, PRESET_CONFIG_DEFAULTS, PRESET_MANAGED_FIELDS, PeopleComponent, PhoneComponent, PriorityComponent, ProgressComponent, RatingComponent, SelectComponent, StatusComponent, TagComponent, TextareaComponent, TextboxComponent, ThemeService, ThemeToggleComponent, WebsiteComponent, evaluateRowCondition, formatDateWithPattern, matchColorRange, normalizeDatatype, normalizeDateFormat, normalizeDateTimeFormat, parseDateWithPattern, resolveRowValue, statusPillColors };
|
|
14724
14785
|
//# sourceMappingURL=eru-grid.mjs.map
|