@memberjunction/ng-entity-relationship-diagram 5.30.0 → 5.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/__tests__/compute-erd-layout.test.d.ts +2 -0
  2. package/dist/__tests__/compute-erd-layout.test.d.ts.map +1 -0
  3. package/dist/__tests__/compute-erd-layout.test.js +207 -0
  4. package/dist/__tests__/compute-erd-layout.test.js.map +1 -0
  5. package/dist/lib/components/entity-details/entity-details.component.d.ts +2 -1
  6. package/dist/lib/components/entity-details/entity-details.component.d.ts.map +1 -1
  7. package/dist/lib/components/entity-details/entity-details.component.js +7 -7
  8. package/dist/lib/components/entity-details/entity-details.component.js.map +1 -1
  9. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.d.ts +10 -4
  10. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.d.ts.map +1 -1
  11. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.js +60 -72
  12. package/dist/lib/components/entity-filter-panel/entity-filter-panel.component.js.map +1 -1
  13. package/dist/lib/components/erd-composite/erd-composite.component.d.ts +4 -1
  14. package/dist/lib/components/erd-composite/erd-composite.component.d.ts.map +1 -1
  15. package/dist/lib/components/erd-composite/erd-composite.component.js +22 -8
  16. package/dist/lib/components/erd-composite/erd-composite.component.js.map +1 -1
  17. package/dist/lib/components/erd-diagram.component.d.ts +169 -443
  18. package/dist/lib/components/erd-diagram.component.d.ts.map +1 -1
  19. package/dist/lib/components/erd-diagram.component.js +916 -1777
  20. package/dist/lib/components/erd-diagram.component.js.map +1 -1
  21. package/dist/lib/components/mj-entity-erd.component.d.ts +3 -2
  22. package/dist/lib/components/mj-entity-erd.component.d.ts.map +1 -1
  23. package/dist/lib/components/mj-entity-erd.component.js +6 -6
  24. package/dist/lib/components/mj-entity-erd.component.js.map +1 -1
  25. package/dist/lib/entity-relationship-diagram.module.d.ts +2 -1
  26. package/dist/lib/entity-relationship-diagram.module.d.ts.map +1 -1
  27. package/dist/lib/entity-relationship-diagram.module.js +9 -3
  28. package/dist/lib/entity-relationship-diagram.module.js.map +1 -1
  29. package/dist/lib/interfaces/erd-types.d.ts +38 -7
  30. package/dist/lib/interfaces/erd-types.d.ts.map +1 -1
  31. package/dist/lib/interfaces/erd-types.js.map +1 -1
  32. package/dist/lib/layout/compute-dagre-layout.d.ts +32 -0
  33. package/dist/lib/layout/compute-dagre-layout.d.ts.map +1 -0
  34. package/dist/lib/layout/compute-dagre-layout.js +168 -0
  35. package/dist/lib/layout/compute-dagre-layout.js.map +1 -0
  36. package/dist/lib/layout/compute-erd-layout.d.ts +103 -0
  37. package/dist/lib/layout/compute-erd-layout.d.ts.map +1 -0
  38. package/dist/lib/layout/compute-erd-layout.js +254 -0
  39. package/dist/lib/layout/compute-erd-layout.js.map +1 -0
  40. package/package.json +6 -5
@@ -1,16 +1,14 @@
1
1
  import { Component, Input, Output, EventEmitter } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  import * as i1 from "@angular/forms";
4
- function EntityFilterPanelComponent_For_20_Template(rf, ctx) { if (rf & 1) {
5
- i0.ɵɵelementStart(0, "option", 12);
6
- i0.ɵɵtext(1);
7
- i0.ɵɵelementEnd();
8
- } if (rf & 2) {
9
- const schema_r1 = ctx.$implicit;
10
- i0.ɵɵproperty("ngValue", schema_r1.value);
11
- i0.ɵɵadvance();
12
- i0.ɵɵtextInterpolate1(" ", schema_r1.text, " ");
13
- } }
4
+ import * as i2 from "@memberjunction/ng-ui-components";
5
+ /** Dropdown items for the Status filter — static list. */
6
+ const STATUS_OPTIONS = [
7
+ { text: 'All Statuses', value: null },
8
+ { text: 'Active', value: 'Active' },
9
+ { text: 'Deprecated', value: 'Deprecated' },
10
+ { text: 'Disabled', value: 'Disabled' },
11
+ ];
14
12
  /**
15
13
  * Entity filter panel component that provides filtering controls for entities.
16
14
  * Supports filtering by schema, entity name, base table, and status.
@@ -38,7 +36,8 @@ export class EntityFilterPanelComponent {
38
36
  resetFilters = new EventEmitter();
39
37
  /** Emitted when close button is clicked */
40
38
  closePanel = new EventEmitter();
41
- distinctSchemas = [];
39
+ schemaOptions = [];
40
+ statusOptions = STATUS_OPTIONS;
42
41
  ngOnInit() {
43
42
  this.updateDistinctSchemas();
44
43
  }
@@ -47,9 +46,16 @@ export class EntityFilterPanelComponent {
47
46
  this.updateDistinctSchemas();
48
47
  }
49
48
  }
49
+ onSchemaChange(value) {
50
+ this.filters = { ...this.filters, schemaName: value ?? null };
51
+ this.emitFilterChange();
52
+ }
53
+ onStatusChange(value) {
54
+ this.filters = { ...this.filters, entityStatus: value ?? null };
55
+ this.emitFilterChange();
56
+ }
50
57
  onFilterChange() {
51
- this.filtersChange.emit(this.filters);
52
- this.filterChange.emit();
58
+ this.emitFilterChange();
53
59
  }
54
60
  resetAllFilters() {
55
61
  this.resetFilters.emit();
@@ -57,6 +63,10 @@ export class EntityFilterPanelComponent {
57
63
  toggleFilterPanel() {
58
64
  this.closePanel.emit();
59
65
  }
66
+ emitFilterChange() {
67
+ this.filtersChange.emit(this.filters);
68
+ this.filterChange.emit();
69
+ }
60
70
  updateDistinctSchemas() {
61
71
  const schemas = new Set();
62
72
  this.entities.forEach(entity => {
@@ -64,12 +74,13 @@ export class EntityFilterPanelComponent {
64
74
  schemas.add(entity.SchemaName);
65
75
  }
66
76
  });
67
- this.distinctSchemas = Array.from(schemas)
68
- .sort()
69
- .map(schema => ({ text: schema, value: schema }));
77
+ this.schemaOptions = [
78
+ { text: 'All Schemas', value: null },
79
+ ...Array.from(schemas).sort().map(schema => ({ text: schema, value: schema })),
80
+ ];
70
81
  }
71
82
  static ɵfac = function EntityFilterPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || EntityFilterPanelComponent)(); };
72
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityFilterPanelComponent, selectors: [["mj-entity-filter-panel"]], inputs: { entities: "entities", filteredEntities: "filteredEntities", filters: "filters" }, outputs: { filtersChange: "filtersChange", filterChange: "filterChange", resetFilters: "resetFilters", closePanel: "closePanel" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 48, vars: 8, consts: [[1, "filter-panel"], [1, "filter-panel-header"], [1, "filter-summary-inline"], [1, "summary-value"], [1, "summary-label"], [1, "close-btn", 3, "click"], [1, "fa-solid", "fa-times"], [1, "filter-content"], [1, "filter-group"], [1, "filter-label"], [1, "fa-solid", "fa-database"], [1, "filter-select", 3, "ngModelChange", "ngModel"], [3, "ngValue"], [1, "fa-solid", "fa-search"], ["type", "text", "placeholder", "Search entities...", 1, "filter-input", 3, "ngModelChange", "input", "ngModel"], [1, "fa-solid", "fa-table"], ["type", "text", "placeholder", "Search tables...", 1, "filter-input", 3, "ngModelChange", "input", "ngModel"], [1, "fa-solid", "fa-check-circle"], ["value", "Active"], ["value", "Deprecated"], ["value", "Disabled"], [1, "filter-actions"], ["title", "Reset all filters", 1, "reset-btn", 3, "click"], [1, "fa-solid", "fa-undo"]], template: function EntityFilterPanelComponent_Template(rf, ctx) { if (rf & 1) {
83
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: EntityFilterPanelComponent, selectors: [["mj-entity-filter-panel"]], inputs: { entities: "entities", filteredEntities: "filteredEntities", filters: "filters" }, outputs: { filtersChange: "filtersChange", filterChange: "filterChange", resetFilters: "resetFilters", closePanel: "closePanel" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], decls: 36, vars: 10, consts: [[1, "filter-panel"], [1, "filter-panel-header"], [1, "filter-summary-inline"], [1, "summary-value"], [1, "summary-label"], ["type", "button", "mjButton", "", "variant", "icon", "size", "sm", "aria-label", "Close filter panel", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-times"], [1, "filter-content"], [1, "filter-group"], [1, "filter-label"], ["aria-hidden", "true", 1, "fa-solid", "fa-database"], ["TextField", "text", "ValueField", "value", 1, "filter-dropdown", 3, "ValueChange", "Data", "ValuePrimitive", "ngModel"], ["aria-hidden", "true", 1, "fa-solid", "fa-magnifying-glass"], ["type", "text", "placeholder", "Search entities...", 1, "mj-input", "filter-input", 3, "ngModelChange", "ngModel"], ["aria-hidden", "true", 1, "fa-solid", "fa-table"], ["type", "text", "placeholder", "Search tables...", 1, "mj-input", "filter-input", 3, "ngModelChange", "ngModel"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-check"], [1, "filter-actions"], ["type", "button", "mjButton", "", "variant", "secondary", "size", "md", "title", "Reset all filters", 1, "reset-btn", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrow-rotate-left"]], template: function EntityFilterPanelComponent_Template(rf, ctx) { if (rf & 1) {
73
84
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "h3");
74
85
  i0.ɵɵtext(3, "Entity Filters");
75
86
  i0.ɵɵelementEnd();
@@ -81,59 +92,42 @@ export class EntityFilterPanelComponent {
81
92
  i0.ɵɵelementEnd()();
82
93
  i0.ɵɵelementStart(9, "button", 5);
83
94
  i0.ɵɵlistener("click", function EntityFilterPanelComponent_Template_button_click_9_listener() { return ctx.toggleFilterPanel(); });
84
- i0.ɵɵelement(10, "span", 6);
95
+ i0.ɵɵelement(10, "i", 6);
85
96
  i0.ɵɵelementEnd()();
86
97
  i0.ɵɵelementStart(11, "div", 7)(12, "div", 8)(13, "label", 9);
87
- i0.ɵɵelement(14, "span", 10);
98
+ i0.ɵɵelement(14, "i", 10);
88
99
  i0.ɵɵtext(15, " Schema ");
89
100
  i0.ɵɵelementEnd();
90
- i0.ɵɵelementStart(16, "select", 11);
91
- i0.ɵɵtwoWayListener("ngModelChange", function EntityFilterPanelComponent_Template_select_ngModelChange_16_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.schemaName, $event) || (ctx.filters.schemaName = $event); return $event; });
92
- i0.ɵɵlistener("ngModelChange", function EntityFilterPanelComponent_Template_select_ngModelChange_16_listener() { return ctx.onFilterChange(); });
93
- i0.ɵɵelementStart(17, "option", 12);
94
- i0.ɵɵtext(18, "All Schemas");
95
- i0.ɵɵelementEnd();
96
- i0.ɵɵrepeaterCreate(19, EntityFilterPanelComponent_For_20_Template, 2, 2, "option", 12, i0.ɵɵrepeaterTrackByIdentity);
101
+ i0.ɵɵelementStart(16, "mj-dropdown", 11);
102
+ i0.ɵɵlistener("ValueChange", function EntityFilterPanelComponent_Template_mj_dropdown_ValueChange_16_listener($event) { return ctx.onSchemaChange($event); });
97
103
  i0.ɵɵelementEnd()();
98
- i0.ɵɵelementStart(21, "div", 8)(22, "label", 9);
99
- i0.ɵɵelement(23, "span", 13);
100
- i0.ɵɵtext(24, " Entity Name ");
104
+ i0.ɵɵelementStart(17, "div", 8)(18, "label", 9);
105
+ i0.ɵɵelement(19, "i", 12);
106
+ i0.ɵɵtext(20, " Entity Name ");
101
107
  i0.ɵɵelementEnd();
102
- i0.ɵɵelementStart(25, "input", 14);
103
- i0.ɵɵtwoWayListener("ngModelChange", function EntityFilterPanelComponent_Template_input_ngModelChange_25_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.entityName, $event) || (ctx.filters.entityName = $event); return $event; });
104
- i0.ɵɵlistener("ngModelChange", function EntityFilterPanelComponent_Template_input_ngModelChange_25_listener() { return ctx.onFilterChange(); })("input", function EntityFilterPanelComponent_Template_input_input_25_listener() { return ctx.onFilterChange(); });
108
+ i0.ɵɵelementStart(21, "input", 13);
109
+ i0.ɵɵtwoWayListener("ngModelChange", function EntityFilterPanelComponent_Template_input_ngModelChange_21_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.entityName, $event) || (ctx.filters.entityName = $event); return $event; });
110
+ i0.ɵɵlistener("ngModelChange", function EntityFilterPanelComponent_Template_input_ngModelChange_21_listener() { return ctx.onFilterChange(); });
105
111
  i0.ɵɵelementEnd()();
106
- i0.ɵɵelementStart(26, "div", 8)(27, "label", 9);
107
- i0.ɵɵelement(28, "span", 15);
108
- i0.ɵɵtext(29, " Base Table ");
112
+ i0.ɵɵelementStart(22, "div", 8)(23, "label", 9);
113
+ i0.ɵɵelement(24, "i", 14);
114
+ i0.ɵɵtext(25, " Base Table ");
109
115
  i0.ɵɵelementEnd();
110
- i0.ɵɵelementStart(30, "input", 16);
111
- i0.ɵɵtwoWayListener("ngModelChange", function EntityFilterPanelComponent_Template_input_ngModelChange_30_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.baseTable, $event) || (ctx.filters.baseTable = $event); return $event; });
112
- i0.ɵɵlistener("ngModelChange", function EntityFilterPanelComponent_Template_input_ngModelChange_30_listener() { return ctx.onFilterChange(); })("input", function EntityFilterPanelComponent_Template_input_input_30_listener() { return ctx.onFilterChange(); });
116
+ i0.ɵɵelementStart(26, "input", 15);
117
+ i0.ɵɵtwoWayListener("ngModelChange", function EntityFilterPanelComponent_Template_input_ngModelChange_26_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.baseTable, $event) || (ctx.filters.baseTable = $event); return $event; });
118
+ i0.ɵɵlistener("ngModelChange", function EntityFilterPanelComponent_Template_input_ngModelChange_26_listener() { return ctx.onFilterChange(); });
113
119
  i0.ɵɵelementEnd()();
114
- i0.ɵɵelementStart(31, "div", 8)(32, "label", 9);
115
- i0.ɵɵelement(33, "span", 17);
116
- i0.ɵɵtext(34, " Status ");
120
+ i0.ɵɵelementStart(27, "div", 8)(28, "label", 9);
121
+ i0.ɵɵelement(29, "i", 16);
122
+ i0.ɵɵtext(30, " Status ");
117
123
  i0.ɵɵelementEnd();
118
- i0.ɵɵelementStart(35, "select", 11);
119
- i0.ɵɵtwoWayListener("ngModelChange", function EntityFilterPanelComponent_Template_select_ngModelChange_35_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.filters.entityStatus, $event) || (ctx.filters.entityStatus = $event); return $event; });
120
- i0.ɵɵlistener("ngModelChange", function EntityFilterPanelComponent_Template_select_ngModelChange_35_listener() { return ctx.onFilterChange(); });
121
- i0.ɵɵelementStart(36, "option", 12);
122
- i0.ɵɵtext(37, "All Statuses");
123
- i0.ɵɵelementEnd();
124
- i0.ɵɵelementStart(38, "option", 18);
125
- i0.ɵɵtext(39, "Active");
126
- i0.ɵɵelementEnd();
127
- i0.ɵɵelementStart(40, "option", 19);
128
- i0.ɵɵtext(41, "Deprecated");
129
- i0.ɵɵelementEnd();
130
- i0.ɵɵelementStart(42, "option", 20);
131
- i0.ɵɵtext(43, "Disabled");
132
- i0.ɵɵelementEnd()()();
133
- i0.ɵɵelementStart(44, "div", 21)(45, "button", 22);
134
- i0.ɵɵlistener("click", function EntityFilterPanelComponent_Template_button_click_45_listener() { return ctx.resetAllFilters(); });
135
- i0.ɵɵelement(46, "span", 23);
136
- i0.ɵɵtext(47, " Reset Filters ");
124
+ i0.ɵɵelementStart(31, "mj-dropdown", 11);
125
+ i0.ɵɵlistener("ValueChange", function EntityFilterPanelComponent_Template_mj_dropdown_ValueChange_31_listener($event) { return ctx.onStatusChange($event); });
126
+ i0.ɵɵelementEnd()();
127
+ i0.ɵɵelementStart(32, "div", 17)(33, "button", 18);
128
+ i0.ɵɵlistener("click", function EntityFilterPanelComponent_Template_button_click_33_listener() { return ctx.resetAllFilters(); });
129
+ i0.ɵɵelement(34, "i", 19);
130
+ i0.ɵɵtext(35, " Reset Filters ");
137
131
  i0.ɵɵelementEnd()()()();
138
132
  } if (rf & 2) {
139
133
  i0.ɵɵadvance(6);
@@ -141,24 +135,18 @@ export class EntityFilterPanelComponent {
141
135
  i0.ɵɵadvance(2);
142
136
  i0.ɵɵtextInterpolate1("of ", ctx.entities.length);
143
137
  i0.ɵɵadvance(8);
144
- i0.ɵɵtwoWayProperty("ngModel", ctx.filters.schemaName);
145
- i0.ɵɵadvance();
146
- i0.ɵɵproperty("ngValue", null);
147
- i0.ɵɵadvance(2);
148
- i0.ɵɵrepeater(ctx.distinctSchemas);
149
- i0.ɵɵadvance(6);
138
+ i0.ɵɵproperty("Data", ctx.schemaOptions)("ValuePrimitive", true)("ngModel", ctx.filters.schemaName);
139
+ i0.ɵɵadvance(5);
150
140
  i0.ɵɵtwoWayProperty("ngModel", ctx.filters.entityName);
151
141
  i0.ɵɵadvance(5);
152
142
  i0.ɵɵtwoWayProperty("ngModel", ctx.filters.baseTable);
153
143
  i0.ɵɵadvance(5);
154
- i0.ɵɵtwoWayProperty("ngModel", ctx.filters.entityStatus);
155
- i0.ɵɵadvance();
156
- i0.ɵɵproperty("ngValue", null);
157
- } }, dependencies: [i1.NgSelectOption, i1.ɵNgSelectMultipleOption, i1.DefaultValueAccessor, i1.SelectControlValueAccessor, i1.NgControlStatus, i1.NgModel], styles: ["\n\n\n\n\n\n.filter-panel[_ngcontent-%COMP%] {\n height: 100%;\n background: var(--mj-bg-page);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n\n\n\n.filter-panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n min-width: 0;\n}\n\n.filter-panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.filter-panel-header[_ngcontent-%COMP%] .filter-summary-inline[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.filter-panel-header[_ngcontent-%COMP%] .filter-summary-inline[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 700;\n color: var(--mj-brand-primary);\n}\n\n.filter-panel-header[_ngcontent-%COMP%] .filter-summary-inline[_ngcontent-%COMP%] .summary-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n\n\n.filter-panel-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: transparent;\n color: var(--mj-text-secondary);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.filter-panel-header[_ngcontent-%COMP%] .close-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n\n\n.filter-content[_ngcontent-%COMP%] {\n padding: 16px;\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n}\n\n\n\n.filter-group[_ngcontent-%COMP%] {\n margin-bottom: 24px;\n}\n\n.filter-group[_ngcontent-%COMP%] .filter-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.filter-group[_ngcontent-%COMP%] .filter-label[_ngcontent-%COMP%] .fa-solid[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n width: 16px;\n}\n\n\n\n.filter-group[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%], \n.filter-group[_ngcontent-%COMP%] .filter-select[_ngcontent-%COMP%] {\n width: 100%;\n max-width: 100%;\n padding: 12px 16px;\n font-size: 14px;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n border: 1px solid var(--mj-color-neutral-400);\n border-radius: 4px;\n transition: all 0.2s ease;\n box-sizing: border-box;\n}\n\n.filter-group[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%]:focus, \n.filter-group[_ngcontent-%COMP%] .filter-select[_ngcontent-%COMP%]:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px var(--mj-color-accent-300);\n}\n\n.filter-group[_ngcontent-%COMP%] .filter-input[_ngcontent-%COMP%]::placeholder, \n.filter-group[_ngcontent-%COMP%] .filter-select[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-secondary);\n opacity: 0.6;\n font-style: italic;\n}\n\n.filter-group[_ngcontent-%COMP%] .filter-select[_ngcontent-%COMP%] {\n cursor: pointer;\n}\n\n.filter-group[_ngcontent-%COMP%] .filter-select[_ngcontent-%COMP%] option[_ngcontent-%COMP%] {\n padding: 8px;\n}\n\n\n\n.filter-actions[_ngcontent-%COMP%] {\n margin-top: 24px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n\n\n.filter-actions[_ngcontent-%COMP%] .reset-btn[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n max-width: 100%;\n padding: 10px 24px;\n font-size: 14px;\n font-weight: 500;\n background: transparent;\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-color-neutral-400);\n border-radius: 20px;\n cursor: pointer;\n transition: all 0.2s ease;\n box-sizing: border-box;\n}\n\n.filter-actions[_ngcontent-%COMP%] .reset-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-active);\n border-color: var(--mj-color-neutral-400);\n color: var(--mj-text-primary);\n}\n\n.filter-actions[_ngcontent-%COMP%] .reset-btn[_ngcontent-%COMP%]:active {\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-actions[_ngcontent-%COMP%] .reset-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.filter-actions[_ngcontent-%COMP%] .reset-btn[_ngcontent-%COMP%] .fa-solid[_ngcontent-%COMP%] {\n font-size: 12px;\n}"] });
144
+ i0.ɵɵproperty("Data", ctx.statusOptions)("ValuePrimitive", true)("ngModel", ctx.filters.entityStatus);
145
+ } }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, i2.MJButtonDirective, i2.MJDropdownComponent], styles: ["\n\n\n\n\n\n\n.filter-panel[_ngcontent-%COMP%] {\n height: 100%;\n background: var(--mj-bg-page);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n\n.filter-panel-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n min-width: 0;\n}\n\n.filter-panel-header[_ngcontent-%COMP%] h3[_ngcontent-%COMP%] {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex: 1;\n min-width: 0;\n}\n\n.filter-summary-inline[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-right: 8px;\n}\n\n.filter-summary-inline[_ngcontent-%COMP%] .summary-value[_ngcontent-%COMP%] {\n font-size: 16px;\n font-weight: 700;\n color: var(--mj-brand-primary);\n}\n\n.filter-summary-inline[_ngcontent-%COMP%] .summary-label[_ngcontent-%COMP%] {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.filter-content[_ngcontent-%COMP%] {\n padding: 16px;\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n}\n\n.filter-group[_ngcontent-%COMP%] {\n margin-bottom: 20px;\n}\n\n.filter-label[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.filter-label[_ngcontent-%COMP%] .fa-solid[_ngcontent-%COMP%] {\n color: var(--mj-brand-primary);\n width: 16px;\n text-align: center;\n}\n\n\n\n.filter-dropdown[_ngcontent-%COMP%] {\n display: block;\n width: 100%;\n}\n\n.filter-input[_ngcontent-%COMP%] {\n width: 100%;\n}\n\n.filter-actions[_ngcontent-%COMP%] {\n margin-top: 24px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.reset-btn[_ngcontent-%COMP%] {\n width: 100%;\n}"] });
158
146
  }
159
147
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(EntityFilterPanelComponent, [{
160
148
  type: Component,
161
- args: [{ standalone: false, selector: 'mj-entity-filter-panel', template: "<div class=\"filter-panel\">\n <div class=\"filter-panel-header\">\n <h3>Entity Filters</h3>\n <div class=\"filter-summary-inline\">\n <span class=\"summary-value\">{{ filteredEntities.length }}</span>\n <span class=\"summary-label\">of {{ entities.length }}</span>\n </div>\n <button class=\"close-btn\" (click)=\"toggleFilterPanel()\">\n <span class=\"fa-solid fa-times\"></span>\n </button>\n </div>\n\n <div class=\"filter-content\">\n <!-- Schema Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <span class=\"fa-solid fa-database\"></span>\n Schema\n </label>\n <select\n class=\"filter-select\"\n [(ngModel)]=\"filters.schemaName\"\n (ngModelChange)=\"onFilterChange()\">\n <option [ngValue]=\"null\">All Schemas</option>\n @for (schema of distinctSchemas; track schema) {\n <option [ngValue]=\"schema.value\">\n {{ schema.text }}\n </option>\n }\n </select>\n </div>\n\n <!-- Entity Name Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <span class=\"fa-solid fa-search\"></span>\n Entity Name\n </label>\n <input\n type=\"text\"\n class=\"filter-input\"\n [(ngModel)]=\"filters.entityName\"\n (ngModelChange)=\"onFilterChange()\"\n (input)=\"onFilterChange()\"\n placeholder=\"Search entities...\">\n </div>\n\n <!-- Base Table Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <span class=\"fa-solid fa-table\"></span>\n Base Table\n </label>\n <input\n type=\"text\"\n class=\"filter-input\"\n [(ngModel)]=\"filters.baseTable\"\n (ngModelChange)=\"onFilterChange()\"\n (input)=\"onFilterChange()\"\n placeholder=\"Search tables...\">\n </div>\n\n <!-- Entity Status Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <span class=\"fa-solid fa-check-circle\"></span>\n Status\n </label>\n <select\n class=\"filter-select\"\n [(ngModel)]=\"filters.entityStatus\"\n (ngModelChange)=\"onFilterChange()\">\n <option [ngValue]=\"null\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Deprecated\">Deprecated</option>\n <option value=\"Disabled\">Disabled</option>\n </select>\n </div>\n\n <!-- Reset Button -->\n <div class=\"filter-actions\">\n <button class=\"reset-btn\" (click)=\"resetAllFilters()\" title=\"Reset all filters\">\n <span class=\"fa-solid fa-undo\"></span>\n Reset Filters\n </button>\n </div>\n </div>\n</div>\n", styles: ["/**\n * Entity Filter Panel Component - MJ Design Token Styled\n * MemberJunction design tokens for the entity filter panel\n */\n\n.filter-panel {\n height: 100%;\n background: var(--mj-bg-page);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n\n/* Panel Header */\n.filter-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n min-width: 0;\n}\n\n.filter-panel-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.filter-panel-header .filter-summary-inline {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n.filter-panel-header .filter-summary-inline .summary-value {\n font-size: 16px;\n font-weight: 700;\n color: var(--mj-brand-primary);\n}\n\n.filter-panel-header .filter-summary-inline .summary-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n/* Icon Button for Close */\n.filter-panel-header .close-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: transparent;\n color: var(--mj-text-secondary);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.filter-panel-header .close-btn:hover {\n background: var(--mj-bg-surface-active);\n color: var(--mj-text-primary);\n}\n\n/* Filter Content */\n.filter-content {\n padding: 16px;\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n}\n\n/* Filter Groups */\n.filter-group {\n margin-bottom: 24px;\n}\n\n.filter-group .filter-label {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.filter-group .filter-label .fa-solid {\n color: var(--mj-brand-primary);\n width: 16px;\n}\n\n/* Input Styling */\n.filter-group .filter-input,\n.filter-group .filter-select {\n width: 100%;\n max-width: 100%;\n padding: 12px 16px;\n font-size: 14px;\n background: var(--mj-bg-page);\n color: var(--mj-text-primary);\n border: 1px solid var(--mj-color-neutral-400);\n border-radius: 4px;\n transition: all 0.2s ease;\n box-sizing: border-box;\n}\n\n.filter-group .filter-input:focus,\n.filter-group .filter-select:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px var(--mj-color-accent-300);\n}\n\n.filter-group .filter-input::placeholder,\n.filter-group .filter-select::placeholder {\n color: var(--mj-text-secondary);\n opacity: 0.6;\n font-style: italic;\n}\n\n.filter-group .filter-select {\n cursor: pointer;\n}\n\n.filter-group .filter-select option {\n padding: 8px;\n}\n\n/* Filter Actions */\n.filter-actions {\n margin-top: 24px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* Outlined Button for Reset */\n.filter-actions .reset-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n width: 100%;\n max-width: 100%;\n padding: 10px 24px;\n font-size: 14px;\n font-weight: 500;\n background: transparent;\n color: var(--mj-text-secondary);\n border: 1px solid var(--mj-color-neutral-400);\n border-radius: 20px;\n cursor: pointer;\n transition: all 0.2s ease;\n box-sizing: border-box;\n}\n\n.filter-actions .reset-btn:hover {\n background: var(--mj-bg-surface-active);\n border-color: var(--mj-color-neutral-400);\n color: var(--mj-text-primary);\n}\n\n.filter-actions .reset-btn:active {\n background: var(--mj-bg-surface-sunken);\n}\n\n.filter-actions .reset-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.filter-actions .reset-btn .fa-solid {\n font-size: 12px;\n}\n"] }]
149
+ args: [{ standalone: false, selector: 'mj-entity-filter-panel', template: "<div class=\"filter-panel\">\n <div class=\"filter-panel-header\">\n <h3>Entity Filters</h3>\n <div class=\"filter-summary-inline\">\n <span class=\"summary-value\">{{ filteredEntities.length }}</span>\n <span class=\"summary-label\">of {{ entities.length }}</span>\n </div>\n <button type=\"button\" mjButton variant=\"icon\" size=\"sm\" (click)=\"toggleFilterPanel()\" aria-label=\"Close filter panel\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"filter-content\">\n <!-- Schema Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n Schema\n </label>\n <mj-dropdown\n class=\"filter-dropdown\"\n [Data]=\"schemaOptions\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [ngModel]=\"filters.schemaName\"\n (ValueChange)=\"onSchemaChange($event)\">\n </mj-dropdown>\n </div>\n\n <!-- Entity Name Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <i class=\"fa-solid fa-magnifying-glass\" aria-hidden=\"true\"></i>\n Entity Name\n </label>\n <input\n type=\"text\"\n class=\"mj-input filter-input\"\n [(ngModel)]=\"filters.entityName\"\n (ngModelChange)=\"onFilterChange()\"\n placeholder=\"Search entities...\">\n </div>\n\n <!-- Base Table Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <i class=\"fa-solid fa-table\" aria-hidden=\"true\"></i>\n Base Table\n </label>\n <input\n type=\"text\"\n class=\"mj-input filter-input\"\n [(ngModel)]=\"filters.baseTable\"\n (ngModelChange)=\"onFilterChange()\"\n placeholder=\"Search tables...\">\n </div>\n\n <!-- Entity Status Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <i class=\"fa-solid fa-circle-check\" aria-hidden=\"true\"></i>\n Status\n </label>\n <mj-dropdown\n class=\"filter-dropdown\"\n [Data]=\"statusOptions\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [ngModel]=\"filters.entityStatus\"\n (ValueChange)=\"onStatusChange($event)\">\n </mj-dropdown>\n </div>\n\n <!-- Reset Button -->\n <div class=\"filter-actions\">\n <button type=\"button\" mjButton variant=\"secondary\" size=\"md\" class=\"reset-btn\" (click)=\"resetAllFilters()\" title=\"Reset all filters\">\n <i class=\"fa-solid fa-arrow-rotate-left\" aria-hidden=\"true\"></i>\n Reset Filters\n </button>\n </div>\n </div>\n</div>\n", styles: ["/**\n * Entity Filter Panel Component\n * Uses standardized MJ UI components (mjButton, mj-dropdown, .mj-input) for\n * form controls \u2014 this stylesheet only covers panel layout + labels.\n */\n\n.filter-panel {\n height: 100%;\n background: var(--mj-bg-page);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n min-width: 0;\n}\n\n.filter-panel-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n min-width: 0;\n}\n\n.filter-panel-header h3 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n flex: 1;\n min-width: 0;\n}\n\n.filter-summary-inline {\n display: flex;\n align-items: center;\n gap: 4px;\n margin-right: 8px;\n}\n\n.filter-summary-inline .summary-value {\n font-size: 16px;\n font-weight: 700;\n color: var(--mj-brand-primary);\n}\n\n.filter-summary-inline .summary-label {\n font-size: 12px;\n color: var(--mj-text-secondary);\n}\n\n.filter-content {\n padding: 16px;\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n}\n\n.filter-group {\n margin-bottom: 20px;\n}\n\n.filter-label {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 8px;\n font-size: 14px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.filter-label .fa-solid {\n color: var(--mj-brand-primary);\n width: 16px;\n text-align: center;\n}\n\n/* Ensure the MJ dropdown takes the full row width like the inputs. */\n.filter-dropdown {\n display: block;\n width: 100%;\n}\n\n.filter-input {\n width: 100%;\n}\n\n.filter-actions {\n margin-top: 24px;\n padding-top: 16px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.reset-btn {\n width: 100%;\n}\n"] }]
162
150
  }], null, { entities: [{
163
151
  type: Input
164
152
  }], filteredEntities: [{
@@ -174,5 +162,5 @@ export class EntityFilterPanelComponent {
174
162
  }], closePanel: [{
175
163
  type: Output
176
164
  }] }); })();
177
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityFilterPanelComponent, { className: "EntityFilterPanelComponent", filePath: "src/lib/components/entity-filter-panel/entity-filter-panel.component.ts", lineNumber: 27 }); })();
165
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(EntityFilterPanelComponent, { className: "EntityFilterPanelComponent", filePath: "src/lib/components/entity-filter-panel/entity-filter-panel.component.ts", lineNumber: 40 }); })();
178
166
  //# sourceMappingURL=entity-filter-panel.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entity-filter-panel.component.js","sourceRoot":"","sources":["../../../../src/lib/components/entity-filter-panel/entity-filter-panel.component.ts","../../../../src/lib/components/entity-filter-panel/entity-filter-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';\nimport { EntityInfo } from '@memberjunction/core';\n\n/**\n * Filter configuration for entity filtering.\n */\nexport interface EntityFilter {\n schemaName: string | null;\n entityName: string;\n entityStatus: string | null;\n baseTable: string;\n}\n\n/**\n * Entity filter panel component that provides filtering controls for entities.\n * Supports filtering by schema, entity name, base table, and status.\n *\n * This component is designed to be used alongside the ERD diagram to filter\n * which entities are displayed.\n */\n@Component({\n standalone: false,\n selector: 'mj-entity-filter-panel',\n templateUrl: './entity-filter-panel.component.html',\n styleUrls: ['./entity-filter-panel.component.css']\n})\nexport class EntityFilterPanelComponent implements OnInit, OnChanges {\n /** All entities available for filtering */\n @Input() entities: EntityInfo[] = [];\n\n /** Currently filtered entities (for display count) */\n @Input() filteredEntities: EntityInfo[] = [];\n\n /** Current filter values */\n @Input() filters: EntityFilter = {\n schemaName: null,\n entityName: '',\n entityStatus: null,\n baseTable: '',\n };\n\n /** Emitted when any filter value changes */\n @Output() filtersChange = new EventEmitter<EntityFilter>();\n\n /** Emitted when filter is applied (for debouncing) */\n @Output() filterChange = new EventEmitter<void>();\n\n /** Emitted when reset button is clicked */\n @Output() resetFilters = new EventEmitter<void>();\n\n /** Emitted when close button is clicked */\n @Output() closePanel = new EventEmitter<void>();\n\n public distinctSchemas: Array<{ text: string; value: string }> = [];\n\n ngOnInit(): void {\n this.updateDistinctSchemas();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['entities']) {\n this.updateDistinctSchemas();\n }\n }\n\n public onFilterChange(): void {\n this.filtersChange.emit(this.filters);\n this.filterChange.emit();\n }\n\n public resetAllFilters(): void {\n this.resetFilters.emit();\n }\n\n public toggleFilterPanel(): void {\n this.closePanel.emit();\n }\n\n private updateDistinctSchemas(): void {\n const schemas = new Set<string>();\n this.entities.forEach(entity => {\n if (entity.SchemaName) {\n schemas.add(entity.SchemaName);\n }\n });\n\n this.distinctSchemas = Array.from(schemas)\n .sort()\n .map(schema => ({ text: schema, value: schema }));\n }\n}\n","<div class=\"filter-panel\">\n <div class=\"filter-panel-header\">\n <h3>Entity Filters</h3>\n <div class=\"filter-summary-inline\">\n <span class=\"summary-value\">{{ filteredEntities.length }}</span>\n <span class=\"summary-label\">of {{ entities.length }}</span>\n </div>\n <button class=\"close-btn\" (click)=\"toggleFilterPanel()\">\n <span class=\"fa-solid fa-times\"></span>\n </button>\n </div>\n\n <div class=\"filter-content\">\n <!-- Schema Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <span class=\"fa-solid fa-database\"></span>\n Schema\n </label>\n <select\n class=\"filter-select\"\n [(ngModel)]=\"filters.schemaName\"\n (ngModelChange)=\"onFilterChange()\">\n <option [ngValue]=\"null\">All Schemas</option>\n @for (schema of distinctSchemas; track schema) {\n <option [ngValue]=\"schema.value\">\n {{ schema.text }}\n </option>\n }\n </select>\n </div>\n\n <!-- Entity Name Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <span class=\"fa-solid fa-search\"></span>\n Entity Name\n </label>\n <input\n type=\"text\"\n class=\"filter-input\"\n [(ngModel)]=\"filters.entityName\"\n (ngModelChange)=\"onFilterChange()\"\n (input)=\"onFilterChange()\"\n placeholder=\"Search entities...\">\n </div>\n\n <!-- Base Table Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <span class=\"fa-solid fa-table\"></span>\n Base Table\n </label>\n <input\n type=\"text\"\n class=\"filter-input\"\n [(ngModel)]=\"filters.baseTable\"\n (ngModelChange)=\"onFilterChange()\"\n (input)=\"onFilterChange()\"\n placeholder=\"Search tables...\">\n </div>\n\n <!-- Entity Status Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <span class=\"fa-solid fa-check-circle\"></span>\n Status\n </label>\n <select\n class=\"filter-select\"\n [(ngModel)]=\"filters.entityStatus\"\n (ngModelChange)=\"onFilterChange()\">\n <option [ngValue]=\"null\">All Statuses</option>\n <option value=\"Active\">Active</option>\n <option value=\"Deprecated\">Deprecated</option>\n <option value=\"Disabled\">Disabled</option>\n </select>\n </div>\n\n <!-- Reset Button -->\n <div class=\"filter-actions\">\n <button class=\"reset-btn\" (click)=\"resetAllFilters()\" title=\"Reset all filters\">\n <span class=\"fa-solid fa-undo\"></span>\n Reset Filters\n </button>\n </div>\n </div>\n</div>\n"]}
1
+ {"version":3,"file":"entity-filter-panel.component.js","sourceRoot":"","sources":["../../../../src/lib/components/entity-filter-panel/entity-filter-panel.component.ts","../../../../src/lib/components/entity-filter-panel/entity-filter-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';\nimport { EntityInfo } from '@memberjunction/core';\n\n/**\n * Filter configuration for entity filtering.\n */\nexport interface EntityFilter {\n schemaName: string | null;\n entityName: string;\n entityStatus: string | null;\n baseTable: string;\n}\n\ninterface FilterOption {\n text: string;\n value: string | null;\n}\n\n/** Dropdown items for the Status filter — static list. */\nconst STATUS_OPTIONS: ReadonlyArray<FilterOption> = [\n { text: 'All Statuses', value: null },\n { text: 'Active', value: 'Active' },\n { text: 'Deprecated', value: 'Deprecated' },\n { text: 'Disabled', value: 'Disabled' },\n];\n\n/**\n * Entity filter panel component that provides filtering controls for entities.\n * Supports filtering by schema, entity name, base table, and status.\n *\n * This component is designed to be used alongside the ERD diagram to filter\n * which entities are displayed.\n */\n@Component({\n standalone: false,\n selector: 'mj-entity-filter-panel',\n templateUrl: './entity-filter-panel.component.html',\n styleUrls: ['./entity-filter-panel.component.css']\n})\nexport class EntityFilterPanelComponent implements OnInit, OnChanges {\n /** All entities available for filtering */\n @Input() entities: EntityInfo[] = [];\n\n /** Currently filtered entities (for display count) */\n @Input() filteredEntities: EntityInfo[] = [];\n\n /** Current filter values */\n @Input() filters: EntityFilter = {\n schemaName: null,\n entityName: '',\n entityStatus: null,\n baseTable: '',\n };\n\n /** Emitted when any filter value changes */\n @Output() filtersChange = new EventEmitter<EntityFilter>();\n\n /** Emitted when filter is applied (for debouncing) */\n @Output() filterChange = new EventEmitter<void>();\n\n /** Emitted when reset button is clicked */\n @Output() resetFilters = new EventEmitter<void>();\n\n /** Emitted when close button is clicked */\n @Output() closePanel = new EventEmitter<void>();\n\n public schemaOptions: FilterOption[] = [];\n public readonly statusOptions = STATUS_OPTIONS;\n\n ngOnInit(): void {\n this.updateDistinctSchemas();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['entities']) {\n this.updateDistinctSchemas();\n }\n }\n\n public onSchemaChange(value: unknown): void {\n this.filters = { ...this.filters, schemaName: (value as string | null) ?? null };\n this.emitFilterChange();\n }\n\n public onStatusChange(value: unknown): void {\n this.filters = { ...this.filters, entityStatus: (value as string | null) ?? null };\n this.emitFilterChange();\n }\n\n public onFilterChange(): void {\n this.emitFilterChange();\n }\n\n public resetAllFilters(): void {\n this.resetFilters.emit();\n }\n\n public toggleFilterPanel(): void {\n this.closePanel.emit();\n }\n\n private emitFilterChange(): void {\n this.filtersChange.emit(this.filters);\n this.filterChange.emit();\n }\n\n private updateDistinctSchemas(): void {\n const schemas = new Set<string>();\n this.entities.forEach(entity => {\n if (entity.SchemaName) {\n schemas.add(entity.SchemaName);\n }\n });\n\n this.schemaOptions = [\n { text: 'All Schemas', value: null },\n ...Array.from(schemas).sort().map(schema => ({ text: schema, value: schema })),\n ];\n }\n}\n","<div class=\"filter-panel\">\n <div class=\"filter-panel-header\">\n <h3>Entity Filters</h3>\n <div class=\"filter-summary-inline\">\n <span class=\"summary-value\">{{ filteredEntities.length }}</span>\n <span class=\"summary-label\">of {{ entities.length }}</span>\n </div>\n <button type=\"button\" mjButton variant=\"icon\" size=\"sm\" (click)=\"toggleFilterPanel()\" aria-label=\"Close filter panel\">\n <i class=\"fa-solid fa-times\" aria-hidden=\"true\"></i>\n </button>\n </div>\n\n <div class=\"filter-content\">\n <!-- Schema Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n Schema\n </label>\n <mj-dropdown\n class=\"filter-dropdown\"\n [Data]=\"schemaOptions\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [ngModel]=\"filters.schemaName\"\n (ValueChange)=\"onSchemaChange($event)\">\n </mj-dropdown>\n </div>\n\n <!-- Entity Name Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <i class=\"fa-solid fa-magnifying-glass\" aria-hidden=\"true\"></i>\n Entity Name\n </label>\n <input\n type=\"text\"\n class=\"mj-input filter-input\"\n [(ngModel)]=\"filters.entityName\"\n (ngModelChange)=\"onFilterChange()\"\n placeholder=\"Search entities...\">\n </div>\n\n <!-- Base Table Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <i class=\"fa-solid fa-table\" aria-hidden=\"true\"></i>\n Base Table\n </label>\n <input\n type=\"text\"\n class=\"mj-input filter-input\"\n [(ngModel)]=\"filters.baseTable\"\n (ngModelChange)=\"onFilterChange()\"\n placeholder=\"Search tables...\">\n </div>\n\n <!-- Entity Status Filter -->\n <div class=\"filter-group\">\n <label class=\"filter-label\">\n <i class=\"fa-solid fa-circle-check\" aria-hidden=\"true\"></i>\n Status\n </label>\n <mj-dropdown\n class=\"filter-dropdown\"\n [Data]=\"statusOptions\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [ngModel]=\"filters.entityStatus\"\n (ValueChange)=\"onStatusChange($event)\">\n </mj-dropdown>\n </div>\n\n <!-- Reset Button -->\n <div class=\"filter-actions\">\n <button type=\"button\" mjButton variant=\"secondary\" size=\"md\" class=\"reset-btn\" (click)=\"resetAllFilters()\" title=\"Reset all filters\">\n <i class=\"fa-solid fa-arrow-rotate-left\" aria-hidden=\"true\"></i>\n Reset Filters\n </button>\n </div>\n </div>\n</div>\n"]}
@@ -1,5 +1,6 @@
1
1
  import { EventEmitter, OnInit, OnDestroy } from '@angular/core';
2
2
  import { EntityInfo, EntityFieldInfo } from '@memberjunction/core';
3
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
3
4
  import { MJEntityERDComponent } from '../mj-entity-erd.component';
4
5
  import { EntitySelectedEvent, OpenEntityRecordEvent } from '../mj-entity-erd.component';
5
6
  import { ERDConfig, ERDState } from '../../interfaces/erd-types';
@@ -21,6 +22,8 @@ export interface ERDCompositeState {
21
22
  };
22
23
  fieldsSectionExpanded: boolean;
23
24
  relationshipsSectionExpanded: boolean;
25
+ /** User's preferred layout algorithm — 'schema-grid' (default) or 'dagre'. */
26
+ layoutAlgorithm?: 'schema-grid' | 'dagre';
24
27
  }
25
28
  /**
26
29
  * ERD Composite component that combines the ERD diagram with filter and details panels.
@@ -64,7 +67,7 @@ export interface ERDCompositeState {
64
67
  * }
65
68
  * ```
66
69
  */
67
- export declare class ERDCompositeComponent implements OnInit, OnDestroy {
70
+ export declare class ERDCompositeComponent extends BaseAngularComponent implements OnInit, OnDestroy {
68
71
  mjEntityErd: MJEntityERDComponent;
69
72
  /** Whether the ERD is in a refreshing state */
70
73
  isRefreshingERD: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"erd-composite.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/erd-composite/erd-composite.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"erd-composite.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/erd-composite/erd-composite.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAa,MAAM,eAAe,CAAC;AAGrG,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,sDAAsD,CAAC;;AAEpF;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4BAA4B,EAAE,OAAO,CAAC;IACtC,8EAA8E;IAC9E,eAAe,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAMa,qBAAsB,SAAQ,oBAAqB,YAAW,MAAM,EAAE,SAAS;IACzD,WAAW,EAAG,oBAAoB,CAAC;IAEpE,+CAA+C;IACtC,eAAe,UAAS;IAEjC;;;;OAIG;IACM,aAAa,EAAE,UAAU,EAAE,GAAG,IAAI,CAAQ;IAEnD;;;OAGG;IACM,eAAe,UAAQ;IAEhC;;;OAGG;IACM,KAAK,SAAK;IAEnB;;OAEG;IACM,UAAU,UAAQ;IAE3B,wCAAwC;IACjC,QAAQ,EAAE,UAAU,EAAE,CAAM;IAEnC,sDAAsD;IAC/C,eAAe,EAAE,eAAe,EAAE,CAAM;IAE/C,mDAAmD;IACzC,WAAW,kCAAyC;IAE9D,6EAA6E;IACnE,eAAe,kCAAyC;IAElE,+EAA+E;IACrE,YAAY,2BAAkC;IAExD,wEAAwE;IAC9D,UAAU;oBAAiC,MAAM;kBAAY,MAAM;OAAK;IAG3E,kBAAkB,UAAQ;IAC1B,qBAAqB,UAAQ;IAC7B,4BAA4B,UAAQ;IAE3C,8DAA8D;IACvD,SAAS,EAAE,SAAS,CAA2B;IAG/C,cAAc,EAAE,UAAU,GAAG,IAAI,CAAQ;IACzC,gBAAgB,EAAE,UAAU,EAAE,CAAM;IACpC,YAAY,UAAS;IAGrB,OAAO,EAAE,YAAY,CAK1B;IAGF,OAAO,CAAC,kBAAkB,CAAoC;IAC9D,OAAO,CAAC,sBAAsB,CAAoC;IAClE,OAAO,CAAC,mBAAmB,CAAuB;IAE5C,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB/B,WAAW,IAAI,IAAI;YAML,QAAQ;IAatB,OAAO,CAAC,oBAAoB;IAwBrB,cAAc,IAAI,IAAI;IAItB,eAAe,CAAC,UAAU,EAAE,YAAY,GAAG,IAAI;IAK/C,cAAc,IAAI,IAAI;IAUtB,mBAAmB,IAAI,IAAI;IAY3B,kBAAkB,IAAI,IAAI;IAO1B,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAejD;;;OAGG;IACI,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAM5D;;;OAGG;IACI,eAAe,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI;IAI1D;;OAEG;IACI,gBAAgB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IAKxC,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAIxC,qBAAqB,IAAI,IAAI;IAK7B,4BAA4B,IAAI,IAAI;IAKpC,YAAY,CAAC,KAAK,EAAE;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,GAAG,IAAI;IAIjE,sBAAsB,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI;IAUpD,OAAO,CAAC,YAAY;IAkCpB,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,UAAU;IAkBlB;;;OAGG;IACI,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAgC7D;;OAEG;IACI,UAAU,IAAI,IAAI;IAMzB;;OAEG;IACI,QAAQ,IAAI,iBAAiB;yCAnWzB,qBAAqB;2CAArB,qBAAqB;CAsWjC"}
@@ -1,8 +1,8 @@
1
1
  import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
2
2
  import { Subject } from 'rxjs';
3
3
  import { debounceTime } from 'rxjs/operators';
4
- import { Metadata } from '@memberjunction/core';
5
4
  import { UUIDsEqual } from '@memberjunction/global';
5
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
6
6
  import { MJEntityERDComponent } from '../mj-entity-erd.component';
7
7
  import * as i0 from "@angular/core";
8
8
  import * as i1 from "angular-split";
@@ -73,7 +73,7 @@ function ERDCompositeComponent_Conditional_6_Template(rf, ctx) { if (rf & 1) {
73
73
  * }
74
74
  * ```
75
75
  */
76
- export class ERDCompositeComponent {
76
+ export class ERDCompositeComponent extends BaseAngularComponent {
77
77
  mjEntityErd;
78
78
  /** Whether the ERD is in a refreshing state */
79
79
  isRefreshingERD = false;
@@ -154,7 +154,7 @@ export class ERDCompositeComponent {
154
154
  }
155
155
  async loadData() {
156
156
  // Load entities from metadata (always needed for allEntityFields and relationship lookups)
157
- const md = new Metadata();
157
+ const md = this.ProviderToUse;
158
158
  this.entities = md.Entities;
159
159
  // Load all entity fields from entities
160
160
  this.allEntityFields = this.entities
@@ -210,6 +210,13 @@ export class ERDCompositeComponent {
210
210
  }
211
211
  onEntitySelected(entity) {
212
212
  this.selectedEntity = entity;
213
+ // Bring the entity into view in the diagram and emit nodeSelected
214
+ // upstream so the focus + highlight logic kicks in. Done in a
215
+ // microtask so the [focusEntityId] binding flushes first and the
216
+ // inner diagram has the new focus state when we ask it to center.
217
+ queueMicrotask(() => {
218
+ this.mjEntityErd?.zoomToEntity(entity.ID);
219
+ });
213
220
  this.emitStateChange();
214
221
  this.emitUserStateChange();
215
222
  }
@@ -305,6 +312,7 @@ export class ERDCompositeComponent {
305
312
  panPosition: { x: 0, y: 0 },
306
313
  fieldsSectionExpanded: this.fieldsSectionExpanded,
307
314
  relationshipsSectionExpanded: this.relationshipsSectionExpanded,
315
+ layoutAlgorithm: this.mjEntityErd?.erdDiagram?.activeLayout ?? 'schema-grid',
308
316
  };
309
317
  }
310
318
  // ============================================================================
@@ -336,6 +344,12 @@ export class ERDCompositeComponent {
336
344
  else {
337
345
  this.selectedEntity = null;
338
346
  }
347
+ // Restore preferred layout algorithm. Deferred to microtask so the
348
+ // diagram has mounted by the time we set it.
349
+ if (state.layoutAlgorithm) {
350
+ const algo = state.layoutAlgorithm;
351
+ queueMicrotask(() => this.mjEntityErd?.erdDiagram?.setLayoutAlgorithm(algo));
352
+ }
339
353
  this.applyFilters();
340
354
  }
341
355
  /**
@@ -352,13 +366,13 @@ export class ERDCompositeComponent {
352
366
  getState() {
353
367
  return this.buildState();
354
368
  }
355
- static ɵfac = function ERDCompositeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ERDCompositeComponent)(); };
369
+ static ɵfac = /*@__PURE__*/ (() => { let ɵERDCompositeComponent_BaseFactory; return function ERDCompositeComponent_Factory(__ngFactoryType__) { return (ɵERDCompositeComponent_BaseFactory || (ɵERDCompositeComponent_BaseFactory = i0.ɵɵgetInheritedFactory(ERDCompositeComponent)))(__ngFactoryType__ || ERDCompositeComponent); }; })();
356
370
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ERDCompositeComponent, selectors: [["mj-erd-composite"]], viewQuery: function ERDCompositeComponent_Query(rf, ctx) { if (rf & 1) {
357
371
  i0.ɵɵviewQuery(MJEntityERDComponent, 5);
358
372
  } if (rf & 2) {
359
373
  let _t;
360
374
  i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.mjEntityErd = _t.first);
361
- } }, inputs: { isRefreshingERD: "isRefreshingERD", focusEntities: "focusEntities", showFilterPanel: "showFilterPanel", depth: "depth", showHeader: "showHeader" }, outputs: { stateChange: "stateChange", userStateChange: "userStateChange", entityOpened: "entityOpened", openRecord: "openRecord" }, standalone: false, decls: 7, vars: 12, consts: [[1, "erd-composite"], ["direction", "horizontal", 3, "dragEnd"], [3, "size", "minSize", "maxSize"], [3, "size"], [1, "erd-pane-container"], ["headerTitle", "Entity Relationship Diagram", 3, "entitySelected", "entityDeselected", "openRecord", "stateChange", "entities", "allEntities", "selectedEntityId", "isRefreshing", "depth", "includeIncoming", "includeOutgoing", "showHeader", "config"], [3, "filtersChange", "filterChange", "resetFilters", "closePanel", "entities", "filteredEntities", "filters"], [3, "openEntity", "closePanel", "fieldsSectionToggle", "relationshipsSectionToggle", "entitySelected", "openRecord", "selectedEntity", "allEntityFields", "fieldsSectionExpanded", "relationshipsSectionExpanded"]], template: function ERDCompositeComponent_Template(rf, ctx) { if (rf & 1) {
375
+ } }, inputs: { isRefreshingERD: "isRefreshingERD", focusEntities: "focusEntities", showFilterPanel: "showFilterPanel", depth: "depth", showHeader: "showHeader" }, outputs: { stateChange: "stateChange", userStateChange: "userStateChange", entityOpened: "entityOpened", openRecord: "openRecord" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 7, vars: 13, consts: [[1, "erd-composite"], ["direction", "horizontal", 3, "dragEnd"], [3, "size", "minSize", "maxSize"], [3, "size"], [1, "erd-pane-container"], ["headerTitle", "Entity Relationship Diagram", 3, "entitySelected", "entityDeselected", "openRecord", "stateChange", "entities", "allEntities", "selectedEntityId", "focusEntityId", "isRefreshing", "depth", "includeIncoming", "includeOutgoing", "showHeader", "config"], [3, "filtersChange", "filterChange", "resetFilters", "closePanel", "entities", "filteredEntities", "filters"], [3, "openEntity", "closePanel", "fieldsSectionToggle", "relationshipsSectionToggle", "entitySelected", "openRecord", "selectedEntity", "allEntityFields", "fieldsSectionExpanded", "relationshipsSectionExpanded"]], template: function ERDCompositeComponent_Template(rf, ctx) { if (rf & 1) {
362
376
  i0.ɵɵelementStart(0, "div", 0)(1, "as-split", 1);
363
377
  i0.ɵɵlistener("dragEnd", function ERDCompositeComponent_Template_as_split_dragEnd_1_listener($event) { return ctx.onSplitterLayoutChange($event); });
364
378
  i0.ɵɵconditionalCreate(2, ERDCompositeComponent_Conditional_2_Template, 2, 6, "as-split-area", 2);
@@ -373,14 +387,14 @@ export class ERDCompositeComponent {
373
387
  i0.ɵɵadvance();
374
388
  i0.ɵɵproperty("size", ctx.selectedEntity ? 60 : ctx.filterPanelVisible ? 80 : 100);
375
389
  i0.ɵɵadvance(2);
376
- i0.ɵɵproperty("entities", ctx.filteredEntities)("allEntities", ctx.entities)("selectedEntityId", (ctx.selectedEntity == null ? null : ctx.selectedEntity.ID) || null)("isRefreshing", ctx.isRefreshingERD)("depth", ctx.depth)("includeIncoming", true)("includeOutgoing", true)("showHeader", ctx.showHeader)("config", ctx.erdConfig);
390
+ i0.ɵɵproperty("entities", ctx.filteredEntities)("allEntities", ctx.entities)("selectedEntityId", (ctx.selectedEntity == null ? null : ctx.selectedEntity.ID) || null)("focusEntityId", (ctx.selectedEntity == null ? null : ctx.selectedEntity.ID) || null)("isRefreshing", ctx.isRefreshingERD)("depth", ctx.depth)("includeIncoming", true)("includeOutgoing", true)("showHeader", ctx.showHeader)("config", ctx.erdConfig);
377
391
  i0.ɵɵadvance();
378
392
  i0.ɵɵconditional(ctx.selectedEntity ? 6 : -1);
379
393
  } }, dependencies: [i1.SplitComponent, i1.SplitAreaComponent, i2.MJEntityERDComponent, i3.EntityDetailsComponent, i4.EntityFilterPanelComponent], styles: ["\n\n\n\n\n\n[_nghost-%COMP%] {\n display: block;\n height: 100%;\n width: 100%;\n}\n\n.erd-composite[_ngcontent-%COMP%] {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n}\n\n.main-splitter[_ngcontent-%COMP%] {\n height: 100%;\n width: 100%;\n}\n\n.main-splitter[_ngcontent-%COMP%] .k-pane[_ngcontent-%COMP%] {\n overflow: hidden;\n}\n\n.erd-pane-container[_ngcontent-%COMP%] {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n\n\n.floating-details-panel[_ngcontent-%COMP%] {\n position: absolute;\n top: 50%;\n right: 20px;\n width: 380px;\n max-height: calc(100% - 40px);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 28px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n overflow: hidden;\n transform: translateY(-50%);\n animation: _ngcontent-%COMP%_slideInFromRight 0.3s ease-out;\n}\n\n@media (max-width: 768px) {\n .floating-details-panel[_ngcontent-%COMP%] {\n right: 10px;\n left: 10px;\n width: auto;\n max-width: none;\n border-radius: 20px;\n }\n}\n\n@media (max-height: 600px) {\n .floating-details-panel[_ngcontent-%COMP%] {\n top: 20px;\n transform: none;\n max-height: calc(100vh - 40px);\n }\n}\n\n@keyframes _ngcontent-%COMP%_slideInFromRight {\n from {\n transform: translateY(-50%) translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateY(-50%) translateX(0);\n opacity: 1;\n }\n}\n\n\n\n.explorer-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n.explorer-header-bar[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n padding: 8px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n\n\n.back-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-color-neutral-400);\n color: var(--mj-text-primary);\n}\n\n.back-btn[_ngcontent-%COMP%]:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.back-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n}\n\n.explorer-container[_ngcontent-%COMP%] mj-entity-explorer[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n}"] });
380
394
  }
381
395
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ERDCompositeComponent, [{
382
396
  type: Component,
383
- args: [{ standalone: false, selector: 'mj-erd-composite', template: "<div class=\"erd-composite\">\n <as-split direction=\"horizontal\" (dragEnd)=\"onSplitterLayoutChange($event)\">\n\n <!-- Filter Panel (Left) -->\n @if (filterPanelVisible) {\n <as-split-area [size]=\"20\" [minSize]=\"15\" [maxSize]=\"30\">\n <mj-entity-filter-panel\n [entities]=\"entities\"\n [filteredEntities]=\"filteredEntities\"\n [filters]=\"filters\"\n (filtersChange)=\"onFiltersChange($event)\"\n (filterChange)=\"onFilterChange()\"\n (resetFilters)=\"onResetFilters()\"\n (closePanel)=\"onToggleFilterPanel()\">\n </mj-entity-filter-panel>\n </as-split-area>\n }\n\n <!-- ERD Diagram (Center) -->\n <as-split-area [size]=\"selectedEntity ? 60 : (filterPanelVisible ? 80 : 100)\">\n <div class=\"erd-pane-container\">\n <mj-entity-erd\n [entities]=\"filteredEntities\"\n [allEntities]=\"entities\"\n [selectedEntityId]=\"selectedEntity?.ID || null\"\n [isRefreshing]=\"isRefreshingERD\"\n [depth]=\"depth\"\n [includeIncoming]=\"true\"\n [includeOutgoing]=\"true\"\n [showHeader]=\"showHeader\"\n [config]=\"erdConfig\"\n headerTitle=\"Entity Relationship Diagram\"\n (entitySelected)=\"onERDEntitySelected($event)\"\n (entityDeselected)=\"onEntityDeselected()\"\n (openRecord)=\"onERDOpenRecord($event)\"\n (stateChange)=\"onERDStateChange($event)\">\n </mj-entity-erd>\n </div>\n </as-split-area>\n\n <!-- Entity Details Panel (Right) -->\n @if (selectedEntity) {\n <as-split-area [size]=\"20\" [minSize]=\"15\" [maxSize]=\"30\">\n <mj-entity-details\n [selectedEntity]=\"selectedEntity\"\n [allEntityFields]=\"allEntityFields\"\n [fieldsSectionExpanded]=\"fieldsSectionExpanded\"\n [relationshipsSectionExpanded]=\"relationshipsSectionExpanded\"\n (openEntity)=\"onEntityOpened($event)\"\n (closePanel)=\"onEntityDeselected()\"\n (fieldsSectionToggle)=\"onFieldsSectionToggle()\"\n (relationshipsSectionToggle)=\"onRelationshipsSectionToggle()\"\n (entitySelected)=\"onEntitySelected($event)\"\n (openRecord)=\"onOpenRecord($event)\">\n </mj-entity-details>\n </as-split-area>\n }\n </as-split>\n</div>\n", styles: ["/**\n * ERD Composite Component - MJ Design Tokens\n * MJ theming for the ERD composite wrapper\n */\n\n:host {\n display: block;\n height: 100%;\n width: 100%;\n}\n\n.erd-composite {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n}\n\n.main-splitter {\n height: 100%;\n width: 100%;\n}\n\n.main-splitter .k-pane {\n overflow: hidden;\n}\n\n.erd-pane-container {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n/* Floating Details Panel - MD3 Styled */\n.floating-details-panel {\n position: absolute;\n top: 50%;\n right: 20px;\n width: 380px;\n max-height: calc(100% - 40px);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 28px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n overflow: hidden;\n transform: translateY(-50%);\n animation: slideInFromRight 0.3s ease-out;\n}\n\n@media (max-width: 768px) {\n .floating-details-panel {\n right: 10px;\n left: 10px;\n width: auto;\n max-width: none;\n border-radius: 20px;\n }\n}\n\n@media (max-height: 600px) {\n .floating-details-panel {\n top: 20px;\n transform: none;\n max-height: calc(100vh - 40px);\n }\n}\n\n@keyframes slideInFromRight {\n from {\n transform: translateY(-50%) translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateY(-50%) translateX(0);\n opacity: 1;\n }\n}\n\n/* Entity Explorer Container - MD3 Styled */\n.explorer-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n.explorer-header-bar {\n display: flex;\n align-items: center;\n padding: 8px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n/* MD3 Outlined Back Button */\n.back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-color-neutral-400);\n color: var(--mj-text-primary);\n}\n\n.back-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.back-btn i {\n font-size: 12px;\n}\n\n.explorer-container mj-entity-explorer {\n flex: 1;\n overflow: hidden;\n}\n"] }]
397
+ args: [{ standalone: false, selector: 'mj-erd-composite', template: "<div class=\"erd-composite\">\n <as-split direction=\"horizontal\" (dragEnd)=\"onSplitterLayoutChange($event)\">\n\n <!-- Filter Panel (Left) -->\n @if (filterPanelVisible) {\n <as-split-area [size]=\"20\" [minSize]=\"15\" [maxSize]=\"30\">\n <mj-entity-filter-panel\n [entities]=\"entities\"\n [filteredEntities]=\"filteredEntities\"\n [filters]=\"filters\"\n (filtersChange)=\"onFiltersChange($event)\"\n (filterChange)=\"onFilterChange()\"\n (resetFilters)=\"onResetFilters()\"\n (closePanel)=\"onToggleFilterPanel()\">\n </mj-entity-filter-panel>\n </as-split-area>\n }\n\n <!-- ERD Diagram (Center) -->\n <as-split-area [size]=\"selectedEntity ? 60 : (filterPanelVisible ? 80 : 100)\">\n <div class=\"erd-pane-container\">\n <mj-entity-erd\n [entities]=\"filteredEntities\"\n [allEntities]=\"entities\"\n [selectedEntityId]=\"selectedEntity?.ID || null\"\n [focusEntityId]=\"selectedEntity?.ID || null\"\n [isRefreshing]=\"isRefreshingERD\"\n [depth]=\"depth\"\n [includeIncoming]=\"true\"\n [includeOutgoing]=\"true\"\n [showHeader]=\"showHeader\"\n [config]=\"erdConfig\"\n headerTitle=\"Entity Relationship Diagram\"\n (entitySelected)=\"onERDEntitySelected($event)\"\n (entityDeselected)=\"onEntityDeselected()\"\n (openRecord)=\"onERDOpenRecord($event)\"\n (stateChange)=\"onERDStateChange($event)\">\n </mj-entity-erd>\n </div>\n </as-split-area>\n\n <!-- Entity Details Panel (Right) -->\n @if (selectedEntity) {\n <as-split-area [size]=\"20\" [minSize]=\"15\" [maxSize]=\"30\">\n <mj-entity-details\n [selectedEntity]=\"selectedEntity\"\n [allEntityFields]=\"allEntityFields\"\n [fieldsSectionExpanded]=\"fieldsSectionExpanded\"\n [relationshipsSectionExpanded]=\"relationshipsSectionExpanded\"\n (openEntity)=\"onEntityOpened($event)\"\n (closePanel)=\"onEntityDeselected()\"\n (fieldsSectionToggle)=\"onFieldsSectionToggle()\"\n (relationshipsSectionToggle)=\"onRelationshipsSectionToggle()\"\n (entitySelected)=\"onEntitySelected($event)\"\n (openRecord)=\"onOpenRecord($event)\">\n </mj-entity-details>\n </as-split-area>\n }\n </as-split>\n</div>\n", styles: ["/**\n * ERD Composite Component - MJ Design Tokens\n * MJ theming for the ERD composite wrapper\n */\n\n:host {\n display: block;\n height: 100%;\n width: 100%;\n}\n\n.erd-composite {\n overflow: hidden;\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n}\n\n.main-splitter {\n height: 100%;\n width: 100%;\n}\n\n.main-splitter .k-pane {\n overflow: hidden;\n}\n\n.erd-pane-container {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n\n/* Floating Details Panel - MD3 Styled */\n.floating-details-panel {\n position: absolute;\n top: 50%;\n right: 20px;\n width: 380px;\n max-height: calc(100% - 40px);\n background: var(--mj-bg-surface-sunken);\n border: 1px solid var(--mj-border-default);\n border-radius: 28px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1000;\n overflow: hidden;\n transform: translateY(-50%);\n animation: slideInFromRight 0.3s ease-out;\n}\n\n@media (max-width: 768px) {\n .floating-details-panel {\n right: 10px;\n left: 10px;\n width: auto;\n max-width: none;\n border-radius: 20px;\n }\n}\n\n@media (max-height: 600px) {\n .floating-details-panel {\n top: 20px;\n transform: none;\n max-height: calc(100vh - 40px);\n }\n}\n\n@keyframes slideInFromRight {\n from {\n transform: translateY(-50%) translateX(100%);\n opacity: 0;\n }\n to {\n transform: translateY(-50%) translateX(0);\n opacity: 1;\n }\n}\n\n/* Entity Explorer Container - MD3 Styled */\n.explorer-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n.explorer-header-bar {\n display: flex;\n align-items: center;\n padding: 8px 16px;\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n/* MD3 Outlined Back Button */\n.back-btn {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-page);\n border: 1px solid var(--mj-border-default);\n border-radius: 20px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n.back-btn:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-color-neutral-400);\n color: var(--mj-text-primary);\n}\n\n.back-btn:focus-visible {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n.back-btn i {\n font-size: 12px;\n}\n\n.explorer-container mj-entity-explorer {\n flex: 1;\n overflow: hidden;\n}\n"] }]
384
398
  }], null, { mjEntityErd: [{
385
399
  type: ViewChild,
386
400
  args: [MJEntityERDComponent]
@@ -403,5 +417,5 @@ export class ERDCompositeComponent {
403
417
  }], openRecord: [{
404
418
  type: Output
405
419
  }] }); })();
406
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ERDCompositeComponent, { className: "ERDCompositeComponent", filePath: "src/lib/components/erd-composite/erd-composite.component.ts", lineNumber: 74 }); })();
420
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ERDCompositeComponent, { className: "ERDCompositeComponent", filePath: "src/lib/components/erd-composite/erd-composite.component.ts", lineNumber: 77 }); })();
407
421
  //# sourceMappingURL=erd-composite.component.js.map