@memberjunction/ng-base-forms 5.37.0 → 5.39.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 (114) hide show
  1. package/README.md +53 -0
  2. package/dist/lib/base-form-component.d.ts +46 -0
  3. package/dist/lib/base-form-component.d.ts.map +1 -1
  4. package/dist/lib/base-form-component.js +68 -2
  5. package/dist/lib/base-form-component.js.map +1 -1
  6. package/dist/lib/container/record-form-container.component.d.ts +77 -1
  7. package/dist/lib/container/record-form-container.component.d.ts.map +1 -1
  8. package/dist/lib/container/record-form-container.component.js +157 -39
  9. package/dist/lib/container/record-form-container.component.js.map +1 -1
  10. package/dist/lib/field/fk-search-utils.d.ts +31 -0
  11. package/dist/lib/field/fk-search-utils.d.ts.map +1 -0
  12. package/dist/lib/field/fk-search-utils.js +47 -0
  13. package/dist/lib/field/fk-search-utils.js.map +1 -0
  14. package/dist/lib/field/form-field.component.d.ts +401 -6
  15. package/dist/lib/field/form-field.component.d.ts.map +1 -1
  16. package/dist/lib/field/form-field.component.js +1646 -214
  17. package/dist/lib/field/form-field.component.js.map +1 -1
  18. package/dist/lib/field/linked-field-options.d.ts +76 -0
  19. package/dist/lib/field/linked-field-options.d.ts.map +1 -0
  20. package/dist/lib/field/linked-field-options.js +80 -0
  21. package/dist/lib/field/linked-field-options.js.map +1 -0
  22. package/dist/lib/host/entity-form-host.component.d.ts +159 -0
  23. package/dist/lib/host/entity-form-host.component.d.ts.map +1 -0
  24. package/dist/lib/host/entity-form-host.component.js +539 -0
  25. package/dist/lib/host/entity-form-host.component.js.map +1 -0
  26. package/dist/lib/interactive-form/interactive-form.component.d.ts +181 -0
  27. package/dist/lib/interactive-form/interactive-form.component.d.ts.map +1 -0
  28. package/dist/lib/interactive-form/interactive-form.component.js +560 -0
  29. package/dist/lib/interactive-form/interactive-form.component.js.map +1 -0
  30. package/dist/lib/isa-related-panel/isa-related-card.component.js +2 -2
  31. package/dist/lib/overlays/base-form-overlay.d.ts +114 -0
  32. package/dist/lib/overlays/base-form-overlay.d.ts.map +1 -0
  33. package/dist/lib/overlays/base-form-overlay.js +227 -0
  34. package/dist/lib/overlays/base-form-overlay.js.map +1 -0
  35. package/dist/lib/overlays/form-dialog.component.d.ts +35 -0
  36. package/dist/lib/overlays/form-dialog.component.d.ts.map +1 -0
  37. package/dist/lib/overlays/form-dialog.component.js +92 -0
  38. package/dist/lib/overlays/form-dialog.component.js.map +1 -0
  39. package/dist/lib/overlays/form-presenter.service.d.ts +37 -0
  40. package/dist/lib/overlays/form-presenter.service.d.ts.map +1 -0
  41. package/dist/lib/overlays/form-presenter.service.js +130 -0
  42. package/dist/lib/overlays/form-presenter.service.js.map +1 -0
  43. package/dist/lib/overlays/form-presenter.types.d.ts +65 -0
  44. package/dist/lib/overlays/form-presenter.types.d.ts.map +1 -0
  45. package/dist/lib/overlays/form-presenter.types.js +25 -0
  46. package/dist/lib/overlays/form-presenter.types.js.map +1 -0
  47. package/dist/lib/overlays/form-slide-in.component.d.ts +38 -0
  48. package/dist/lib/overlays/form-slide-in.component.d.ts.map +1 -0
  49. package/dist/lib/overlays/form-slide-in.component.js +106 -0
  50. package/dist/lib/overlays/form-slide-in.component.js.map +1 -0
  51. package/dist/lib/overlays/form-window.component.d.ts +32 -0
  52. package/dist/lib/overlays/form-window.component.d.ts.map +1 -0
  53. package/dist/lib/overlays/form-window.component.js +93 -0
  54. package/dist/lib/overlays/form-window.component.js.map +1 -0
  55. package/dist/lib/panel/collapsible-panel.component.d.ts +19 -2
  56. package/dist/lib/panel/collapsible-panel.component.d.ts.map +1 -1
  57. package/dist/lib/panel/collapsible-panel.component.js +70 -13
  58. package/dist/lib/panel/collapsible-panel.component.js.map +1 -1
  59. package/dist/lib/panel-slot/base-form-panel.d.ts +97 -0
  60. package/dist/lib/panel-slot/base-form-panel.d.ts.map +1 -0
  61. package/dist/lib/panel-slot/base-form-panel.js +64 -0
  62. package/dist/lib/panel-slot/base-form-panel.js.map +1 -0
  63. package/dist/lib/panel-slot/form-panel-slot.component.d.ts +78 -0
  64. package/dist/lib/panel-slot/form-panel-slot.component.d.ts.map +1 -0
  65. package/dist/lib/panel-slot/form-panel-slot.component.js +227 -0
  66. package/dist/lib/panel-slot/form-panel-slot.component.js.map +1 -0
  67. package/dist/lib/panel-slot/form-slot-coordinator.service.d.ts +57 -0
  68. package/dist/lib/panel-slot/form-slot-coordinator.service.d.ts.map +1 -0
  69. package/dist/lib/panel-slot/form-slot-coordinator.service.js +104 -0
  70. package/dist/lib/panel-slot/form-slot-coordinator.service.js.map +1 -0
  71. package/dist/lib/resolver/form-resolver.service.d.ts +139 -0
  72. package/dist/lib/resolver/form-resolver.service.d.ts.map +1 -0
  73. package/dist/lib/resolver/form-resolver.service.js +235 -0
  74. package/dist/lib/resolver/form-resolver.service.js.map +1 -0
  75. package/dist/lib/section-manager/section-manager.component.js +2 -2
  76. package/dist/lib/toolbar/form-toolbar.component.d.ts +56 -1
  77. package/dist/lib/toolbar/form-toolbar.component.d.ts.map +1 -1
  78. package/dist/lib/toolbar/form-toolbar.component.js +294 -136
  79. package/dist/lib/toolbar/form-toolbar.component.js.map +1 -1
  80. package/dist/lib/types/entity-form-config.d.ts +125 -0
  81. package/dist/lib/types/entity-form-config.d.ts.map +1 -0
  82. package/dist/lib/types/entity-form-config.js +75 -0
  83. package/dist/lib/types/entity-form-config.js.map +1 -0
  84. package/dist/lib/types/form-types.d.ts +24 -0
  85. package/dist/lib/types/form-types.d.ts.map +1 -1
  86. package/dist/lib/types/form-types.js.map +1 -1
  87. package/dist/lib/types/navigation-events.d.ts +64 -2
  88. package/dist/lib/types/navigation-events.d.ts.map +1 -1
  89. package/dist/lib/types/navigation-events.js.map +1 -1
  90. package/dist/lib/types/toolbar-config.d.ts +11 -0
  91. package/dist/lib/types/toolbar-config.d.ts.map +1 -1
  92. package/dist/lib/types/toolbar-config.js +3 -0
  93. package/dist/lib/types/toolbar-config.js.map +1 -1
  94. package/dist/module.d.ts +14 -7
  95. package/dist/module.d.ts.map +1 -1
  96. package/dist/module.js +40 -7
  97. package/dist/module.js.map +1 -1
  98. package/dist/public-api.d.ts +15 -0
  99. package/dist/public-api.d.ts.map +1 -1
  100. package/dist/public-api.js +21 -0
  101. package/dist/public-api.js.map +1 -1
  102. package/package.json +17 -11
  103. package/dist/__tests__/sanity.test.d.ts +0 -2
  104. package/dist/__tests__/sanity.test.d.ts.map +0 -1
  105. package/dist/__tests__/sanity.test.js +0 -12
  106. package/dist/__tests__/sanity.test.js.map +0 -1
  107. package/dist/__tests__/tag-count-badge.test.d.ts +0 -2
  108. package/dist/__tests__/tag-count-badge.test.d.ts.map +0 -1
  109. package/dist/__tests__/tag-count-badge.test.js +0 -70
  110. package/dist/__tests__/tag-count-badge.test.js.map +0 -1
  111. package/dist/lib/__tests__/base-forms.test.d.ts +0 -2
  112. package/dist/lib/__tests__/base-forms.test.d.ts.map +0 -1
  113. package/dist/lib/__tests__/base-forms.test.js +0 -256
  114. package/dist/lib/__tests__/base-forms.test.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-window.component.js","sourceRoot":"","sources":["../../../src/lib/overlays/form-window.component.ts","../../../src/lib/overlays/form-window.component.html"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAElH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;;;;;IC0BzD,AADF,yCAAmB,gBAC8D;IAAxB,wMAAS,oBAAa,KAAC;IAAC,YAAoB;IAAA,iBAAS;IAC5G,iCAA0D;IAArB,wMAAS,iBAAU,KAAC;IAAC,YAAsB;IAClF,AADkF,iBAAS,EACvE;;;IAFiB,cAAmB;IAAnB,wCAAmB;IAAyB,cAAoB;IAApB,2CAAoB;IAClF,cAAmB;IAAnB,wCAAmB;IAAsB,cAAsB;IAAtB,6CAAsB;;;;IAhCtF,oCAOuB;IAArB,4LAAS,iBAAU,KAAC;IAEpB,iDAiBuC;IAArC,AADA,AADA,AADA,AADA,AADA,AADA,AADA,AADA,4MAAS,0BAAmB,KAAC,iMAChB,wBAAiB,KAAC,2MAChB,4BAAqB,KAAC,qMACzB,4BAAqB,KAAC,6MAClB,gCAAyB,KAAC,+MACzB,iCAA0B,KAAC,qNACxB,oCAA6B,KAAC,qNAC9B,oCAA6B,KAAC,uMACrC,6BAAsB,KAAC;IACtC,iBAAsB;IAEtB,gHAAkB;IAMpB,iBAAY;;;IA7BV,AADA,AADA,AADA,AADA,AADA,8BAAgB,gCACQ,uBACT,yBACE,+BACM,+BACA;IAIrB,cAAyB;IAOzB,AADA,AADA,AADA,AADA,AADA,AADA,AADA,8CAAyB,0CACU,yBAClB,2CACkB,mCACR,6BACN,kCACK,6BACL;IAYvB,eAKC;IALD,4CAKC;;AD3BL;;;;;;;;;;;;;;GAcG;AAOH,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IACxD,uCAAuC;IAC9B,KAAK,GAA2B,GAAG,CAAC;IAC7C,wCAAwC;IAC/B,MAAM,GAA2B,GAAG,CAAC;IAC9C,yDAAyD;IAChD,SAAS,GAAG,IAAI,CAAC;IAC1B,yCAAyC;IAChC,SAAS,GAAG,IAAI,CAAC;IAE1B,uEAAuE;IACvE,IAAuB,YAAY,KAAK,OAAO,kBAAkB,CAAC,CAAC,CAAC;iQAXzD,qBAAqB,yBAArB,qBAAqB;6DAArB,qBAAqB;YC7BlC,8FAAe;;YAAf,sCAqCC;4BDXW,YAAY,EAAE,eAAe,gCAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB;;iFAG5F,qBAAqB;cANjC,SAAS;6BACI,IAAI,YACN,gBAAgB,WACjB,CAAC,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,iBAAiB,CAAC;;kBAKvG,KAAK;;kBAEL,KAAK;;kBAEL,KAAK;;kBAEL,KAAK;;kFARK,qBAAqB","sourcesContent":["import { Component, Input } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { MJWindowComponent, MJWindowActionsComponent, MJButtonDirective } from '@memberjunction/ng-ui-components';\n\nimport { BaseFormsModule } from '../../module';\nimport { BaseFormOverlay } from './base-form-overlay';\nimport { DIALOG_FORM_CONFIG } from '../types/entity-form-config';\n\n/**\n * Opens any MemberJunction entity form inside a floating, **non-modal** window\n * (draggable + resizable, no backdrop). Good for \"keep this open while I work\n * elsewhere\" scenarios — comparing records, reference-while-editing, etc.\n *\n * Same host + event surface as {@link MjFormDialogComponent}; only the chrome\n * differs (`mj-window` instead of `mj-dialog`). Defaults to\n * {@link DIALOG_FORM_CONFIG} (no in-form toolbar; the window footer owns\n * Save/Cancel).\n *\n * Standalone — import it directly:\n * ```typescript\n * import { MjFormWindowComponent } from '@memberjunction/ng-base-forms';\n * ```\n */\n@Component({\n standalone: true,\n selector: 'mj-form-window',\n imports: [CommonModule, BaseFormsModule, MJWindowComponent, MJWindowActionsComponent, MJButtonDirective],\n templateUrl: './form-window.component.html',\n})\nexport class MjFormWindowComponent extends BaseFormOverlay {\n /** Window width (px or CSS string). */\n @Input() Width: number | string | null = 760;\n /** Window height (px or CSS string). */\n @Input() Height: number | string | null = 560;\n /** Whether the window can be dragged by its titlebar. */\n @Input() Draggable = true;\n /** Whether the window can be resized. */\n @Input() Resizable = true;\n\n /** Form config. Defaults to the dialog preset (no in-form toolbar). */\n protected override get PresetConfig() { return DIALOG_FORM_CONFIG; }\n}\n","@if (Visible) {\n <mj-window\n [Visible]=\"true\"\n [Title]=\"effectiveTitle\"\n [Width]=\"Width\"\n [Height]=\"Height\"\n [Draggable]=\"Draggable\"\n [Resizable]=\"Resizable\"\n (Close)=\"onCancel()\">\n\n <mj-entity-form-host #host\n [EntityName]=\"EntityName\"\n [PrimaryKey]=\"effectivePrimaryKey!\"\n [Record]=\"Record\"\n [NewRecordValues]=\"NewRecordValues\"\n [SectionName]=\"SectionName\"\n [EditMode]=\"EditMode\"\n [Config]=\"EffectiveConfig\"\n [Provider]=\"Provider\"\n (Saved)=\"onHostSaved($event)\"\n (Dismissed)=\"onHostDismissed()\"\n (FormCreated)=\"onFormCreated($event)\"\n (Navigate)=\"Navigate.emit($event)\"\n (Notification)=\"Notification.emit($event)\"\n (RecordDeleted)=\"RecordDeleted.emit($event)\"\n (RecordSaveFailed)=\"RecordSaveFailed.emit($event)\"\n (ValidationFailed)=\"ValidationFailed.emit($event)\"\n (LoadError)=\"LoadError.emit($event)\">\n </mj-entity-form-host>\n\n @if (ShowFooter) {\n <mj-window-actions>\n <button mjButton variant=\"primary\" [disabled]=\"saving\" (click)=\"onSaveClick()\">{{ SaveButtonText }}</button>\n <button mjButton [disabled]=\"saving\" (click)=\"onCancel()\">{{ CancelButtonText }}</button>\n </mj-window-actions>\n }\n </mj-window>\n}\n"]}
@@ -67,6 +67,16 @@ export declare class MjCollapsiblePanelComponent implements OnInit, OnChanges, A
67
67
  * (Shared PK in IS-A relationships.)
68
68
  */
69
69
  InheritedRecordPrimaryKey?: CompositeKey;
70
+ /**
71
+ * Container-driven hard hide. When true the panel is removed from view
72
+ * regardless of search state — used by the record-form container to honor
73
+ * `EntityFormConfig.showRelatedEntities` / `hiddenSectionKeys` /
74
+ * `visibleSectionKeys`. Composes with (overrides) search visibility so all
75
+ * existing `IsVisible`-based section counts stay correct.
76
+ */
77
+ set Hidden(value: boolean);
78
+ get Hidden(): boolean;
79
+ private _hidden;
70
80
  /** @deprecated Use [SectionKey] instead */
71
81
  set _deprecatedSectionKey(value: string);
72
82
  /** @deprecated Use [SectionName] instead */
@@ -103,7 +113,14 @@ export declare class MjCollapsiblePanelComponent implements OnInit, OnChanges, A
103
113
  get PanelContentHeight(): number | undefined;
104
114
  /** Whether drag-to-reorder is allowed (from FormContext) */
105
115
  get ReorderAllowed(): boolean;
106
- /** Whether the panel is expanded (delegates to form state) */
116
+ /**
117
+ * Whether this panel's header may collapse/expand. Driven by
118
+ * `FormContext.collapsibleSections`; when false the panel renders
119
+ * always-expanded with no toggle chevron (used by dialog/slide-in surfaces
120
+ * that lock sections open). Undefined / true means collapsible.
121
+ */
122
+ get Collapsible(): boolean;
123
+ /** Whether the panel is expanded (delegates to form state; always true when not collapsible) */
107
124
  get Expanded(): boolean;
108
125
  ngOnInit(): void;
109
126
  ngAfterContentInit(): void;
@@ -140,6 +157,6 @@ export declare class MjCollapsiblePanelComponent implements OnInit, OnChanges, A
140
157
  private DebouncePersistHeight;
141
158
  private UpdateVisibilityAndHighlighting;
142
159
  static ɵfac: i0.ɵɵFactoryDeclaration<MjCollapsiblePanelComponent, never>;
143
- static ɵcmp: i0.ɵɵComponentDeclaration<MjCollapsiblePanelComponent, "mj-collapsible-panel", never, { "SectionKey": { "alias": "SectionKey"; "required": false; }; "SectionName": { "alias": "SectionName"; "required": false; }; "Icon": { "alias": "Icon"; "required": false; }; "Form": { "alias": "Form"; "required": false; }; "FormContext": { "alias": "FormContext"; "required": false; }; "Variant": { "alias": "Variant"; "required": false; }; "BadgeCount": { "alias": "BadgeCount"; "required": false; }; "DefaultExpanded": { "alias": "DefaultExpanded"; "required": false; }; "InheritedFromEntity": { "alias": "InheritedFromEntity"; "required": false; }; "InheritedRecordPrimaryKey": { "alias": "InheritedRecordPrimaryKey"; "required": false; }; "_deprecatedSectionKey": { "alias": "sectionKey"; "required": false; }; "_deprecatedSectionName": { "alias": "sectionName"; "required": false; }; "_deprecatedIcon": { "alias": "icon"; "required": false; }; "_deprecatedForm": { "alias": "form"; "required": false; }; "_deprecatedFormContext": { "alias": "formContext"; "required": false; }; }, { "DragStarted": "DragStarted"; "DragEnded": "DragEnded"; "PanelDrop": "PanelDrop"; "Navigate": "Navigate"; }, ["FieldComponents"], ["*"], false, never>;
160
+ static ɵcmp: i0.ɵɵComponentDeclaration<MjCollapsiblePanelComponent, "mj-collapsible-panel", never, { "SectionKey": { "alias": "SectionKey"; "required": false; }; "SectionName": { "alias": "SectionName"; "required": false; }; "Icon": { "alias": "Icon"; "required": false; }; "Form": { "alias": "Form"; "required": false; }; "FormContext": { "alias": "FormContext"; "required": false; }; "Variant": { "alias": "Variant"; "required": false; }; "BadgeCount": { "alias": "BadgeCount"; "required": false; }; "DefaultExpanded": { "alias": "DefaultExpanded"; "required": false; }; "InheritedFromEntity": { "alias": "InheritedFromEntity"; "required": false; }; "InheritedRecordPrimaryKey": { "alias": "InheritedRecordPrimaryKey"; "required": false; }; "Hidden": { "alias": "Hidden"; "required": false; }; "_deprecatedSectionKey": { "alias": "sectionKey"; "required": false; }; "_deprecatedSectionName": { "alias": "sectionName"; "required": false; }; "_deprecatedIcon": { "alias": "icon"; "required": false; }; "_deprecatedForm": { "alias": "form"; "required": false; }; "_deprecatedFormContext": { "alias": "formContext"; "required": false; }; }, { "DragStarted": "DragStarted"; "DragEnded": "DragEnded"; "PanelDrop": "PanelDrop"; "Navigate": "Navigate"; }, ["FieldComponents"], ["*"], false, never>;
144
161
  }
145
162
  //# sourceMappingURL=collapsible-panel.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/panel/collapsible-panel.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"collapsible-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/panel/collapsible-panel.component.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ChangeDetectorRef, inject, ContentChildren, HostBinding, HostListener, ElementRef, ViewChild, NgZone, ViewEncapsulation } from '@angular/core';
2
2
  import { Subject } from 'rxjs';
3
3
  import { takeUntil } from 'rxjs/operators';
4
+ import { IsFormSectionHidden } from '../types/entity-form-config';
4
5
  import { MjFormFieldComponent } from '../field/form-field.component';
5
6
  import { CompositeKey } from '@memberjunction/core';
6
7
  import { EscapeHTML, HighlightSearchMatches } from '@memberjunction/global';
@@ -37,6 +38,15 @@ function MjCollapsiblePanelComponent_Conditional_8_Template(rf, ctx) { if (rf &
37
38
  i0.ɵɵadvance(2);
38
39
  i0.ɵɵtextInterpolate1(" Inherited from ", ctx_r2.InheritedFromEntity, " ");
39
40
  } }
41
+ function MjCollapsiblePanelComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
42
+ i0.ɵɵelementStart(0, "div", 10);
43
+ i0.ɵɵelement(1, "i");
44
+ i0.ɵɵelementEnd();
45
+ } if (rf & 2) {
46
+ const ctx_r2 = i0.ɵɵnextContext();
47
+ i0.ɵɵadvance();
48
+ i0.ɵɵclassMap(ctx_r2.Expanded ? "fa fa-chevron-up" : "fa fa-chevron-down");
49
+ } }
40
50
  /**
41
51
  * Reusable collapsible panel for form sections.
42
52
  *
@@ -100,6 +110,26 @@ export class MjCollapsiblePanelComponent {
100
110
  * (Shared PK in IS-A relationships.)
101
111
  */
102
112
  InheritedRecordPrimaryKey;
113
+ /**
114
+ * Container-driven hard hide. When true the panel is removed from view
115
+ * regardless of search state — used by the record-form container to honor
116
+ * `EntityFormConfig.showRelatedEntities` / `hiddenSectionKeys` /
117
+ * `visibleSectionKeys`. Composes with (overrides) search visibility so all
118
+ * existing `IsVisible`-based section counts stay correct.
119
+ */
120
+ set Hidden(value) {
121
+ if (value !== this._hidden) {
122
+ this._hidden = value;
123
+ // Recompute visibility if content has initialized (FieldComponents present).
124
+ if (this.FieldComponents) {
125
+ this.UpdateVisibilityAndHighlighting();
126
+ }
127
+ }
128
+ }
129
+ get Hidden() {
130
+ return this._hidden;
131
+ }
132
+ _hidden = false;
103
133
  // ---- Deprecated camelCase aliases (backward compat) ----
104
134
  /** @deprecated Use [SectionKey] instead */
105
135
  set _deprecatedSectionKey(value) { this.SectionKey = value; }
@@ -161,8 +191,19 @@ export class MjCollapsiblePanelComponent {
161
191
  get ReorderAllowed() {
162
192
  return this.FormContext?.allowSectionReorder !== false;
163
193
  }
164
- /** Whether the panel is expanded (delegates to form state) */
194
+ /**
195
+ * Whether this panel's header may collapse/expand. Driven by
196
+ * `FormContext.collapsibleSections`; when false the panel renders
197
+ * always-expanded with no toggle chevron (used by dialog/slide-in surfaces
198
+ * that lock sections open). Undefined / true means collapsible.
199
+ */
200
+ get Collapsible() {
201
+ return this.FormContext?.collapsibleSections !== false;
202
+ }
203
+ /** Whether the panel is expanded (delegates to form state; always true when not collapsible) */
165
204
  get Expanded() {
205
+ if (!this.Collapsible)
206
+ return true;
166
207
  const formRef = this.Form;
167
208
  return formRef?.IsSectionExpanded ? formRef.IsSectionExpanded(this.SectionKey, this.DefaultExpanded) : true;
168
209
  }
@@ -204,6 +245,8 @@ export class MjCollapsiblePanelComponent {
204
245
  }
205
246
  // ---- Actions ----
206
247
  Toggle() {
248
+ if (!this.Collapsible)
249
+ return;
207
250
  const formRef = this.Form;
208
251
  if (formRef?.SetSectionExpanded) {
209
252
  formRef.SetSectionExpanded(this.SectionKey, !this.Expanded);
@@ -358,6 +401,16 @@ export class MjCollapsiblePanelComponent {
358
401
  }, 500);
359
402
  }
360
403
  UpdateVisibilityAndHighlighting() {
404
+ // Hard hide takes precedence over search state. Driven by an explicit
405
+ // `Hidden` input OR the form config's section-visibility rules carried on
406
+ // FormContext (which also reach slot-injected BaseFormPanels, since every
407
+ // panel receives FormContext).
408
+ if (this._hidden || IsFormSectionHidden(this.FormContext, this.SectionKey, this.Variant)) {
409
+ this.IsVisible = false;
410
+ this.DisplayName = EscapeHTML(this.SectionName);
411
+ this.cdr.markForCheck();
412
+ return;
413
+ }
361
414
  const searchTerm = (this.FormContext?.sectionFilter || '').toLowerCase().trim();
362
415
  if (!searchTerm) {
363
416
  this.IsVisible = true;
@@ -391,7 +444,7 @@ export class MjCollapsiblePanelComponent {
391
444
  } if (rf & 2) {
392
445
  i0.ɵɵclassMap(ctx.HostClass);
393
446
  i0.ɵɵstyleProp("order", ctx.CssOrder);
394
- } }, inputs: { SectionKey: "SectionKey", SectionName: "SectionName", Icon: "Icon", Form: "Form", FormContext: "FormContext", Variant: "Variant", BadgeCount: "BadgeCount", DefaultExpanded: "DefaultExpanded", InheritedFromEntity: "InheritedFromEntity", InheritedRecordPrimaryKey: "InheritedRecordPrimaryKey", _deprecatedSectionKey: [0, "sectionKey", "_deprecatedSectionKey"], _deprecatedSectionName: [0, "sectionName", "_deprecatedSectionName"], _deprecatedIcon: [0, "icon", "_deprecatedIcon"], _deprecatedForm: [0, "form", "_deprecatedForm"], _deprecatedFormContext: [0, "formContext", "_deprecatedFormContext"] }, outputs: { DragStarted: "DragStarted", DragEnded: "DragEnded", PanelDrop: "PanelDrop", Navigate: "Navigate" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], ngContentSelectors: _c1, decls: 15, vars: 17, consts: [["panelContent", ""], [1, "mj-forms-panel"], ["role", "button", "tabindex", "0", 1, "mj-forms-panel-header", 3, "click"], ["title", "Drag to reorder sections", "draggable", "true", 1, "mj-forms-drag-handle"], [1, "mj-forms-panel-title-group"], [1, "mj-forms-panel-icon"], [1, "mj-forms-panel-title"], [3, "innerHTML"], [1, "mj-forms-row-count-badge", 3, "mj-forms-row-count-badge--zero"], [1, "mj-forms-inherited-badge", 3, "title"], [1, "mj-forms-panel-chevron"], [1, "mj-forms-panel-body"], [1, "mj-forms-panel-content"], ["title", "Drag to reorder sections", "draggable", "true", 1, "mj-forms-drag-handle", 3, "dragstart", "dragend", "click"], [1, "fa-solid", "fa-grip-vertical"], [1, "mj-forms-row-count-badge"], [1, "mj-forms-inherited-badge", 3, "click", "title"], [1, "fa-solid", "fa-arrow-up"]], template: function MjCollapsiblePanelComponent_Template(rf, ctx) { if (rf & 1) {
447
+ } }, inputs: { SectionKey: "SectionKey", SectionName: "SectionName", Icon: "Icon", Form: "Form", FormContext: "FormContext", Variant: "Variant", BadgeCount: "BadgeCount", DefaultExpanded: "DefaultExpanded", InheritedFromEntity: "InheritedFromEntity", InheritedRecordPrimaryKey: "InheritedRecordPrimaryKey", Hidden: "Hidden", _deprecatedSectionKey: [0, "sectionKey", "_deprecatedSectionKey"], _deprecatedSectionName: [0, "sectionName", "_deprecatedSectionName"], _deprecatedIcon: [0, "icon", "_deprecatedIcon"], _deprecatedForm: [0, "form", "_deprecatedForm"], _deprecatedFormContext: [0, "formContext", "_deprecatedFormContext"] }, outputs: { DragStarted: "DragStarted", DragEnded: "DragEnded", PanelDrop: "PanelDrop", Navigate: "Navigate" }, standalone: false, features: [i0.ɵɵNgOnChangesFeature], ngContentSelectors: _c1, decls: 14, vars: 20, consts: [["panelContent", ""], [1, "mj-forms-panel"], [1, "mj-forms-panel-header", 3, "click"], ["title", "Drag to reorder sections", "draggable", "true", 1, "mj-forms-drag-handle"], [1, "mj-forms-panel-title-group"], [1, "mj-forms-panel-icon"], [1, "mj-forms-panel-title"], [3, "innerHTML"], [1, "mj-forms-row-count-badge", 3, "mj-forms-row-count-badge--zero"], [1, "mj-forms-inherited-badge", 3, "title"], [1, "mj-forms-panel-chevron"], [1, "mj-forms-panel-body"], [1, "mj-forms-panel-content"], ["title", "Drag to reorder sections", "draggable", "true", 1, "mj-forms-drag-handle", 3, "dragstart", "dragend", "click"], [1, "fa-solid", "fa-grip-vertical"], [1, "mj-forms-row-count-badge"], [1, "mj-forms-inherited-badge", 3, "click", "title"], [1, "fa-solid", "fa-arrow-up"]], template: function MjCollapsiblePanelComponent_Template(rf, ctx) { if (rf & 1) {
395
448
  const _r1 = i0.ɵɵgetCurrentView();
396
449
  i0.ɵɵprojectionDef();
397
450
  i0.ɵɵelementStart(0, "div", 1)(1, "div", 2);
@@ -404,16 +457,18 @@ export class MjCollapsiblePanelComponent {
404
457
  i0.ɵɵconditionalCreate(7, MjCollapsiblePanelComponent_Conditional_7_Template, 2, 3, "span", 8);
405
458
  i0.ɵɵelementEnd()();
406
459
  i0.ɵɵconditionalCreate(8, MjCollapsiblePanelComponent_Conditional_8_Template, 3, 2, "a", 9);
407
- i0.ɵɵelementStart(9, "div", 10);
408
- i0.ɵɵelement(10, "i");
409
- i0.ɵɵelementEnd()();
410
- i0.ɵɵelementStart(11, "div", 11)(12, "div", 12, 0);
411
- i0.ɵɵprojection(14);
460
+ i0.ɵɵconditionalCreate(9, MjCollapsiblePanelComponent_Conditional_9_Template, 2, 2, "div", 10);
461
+ i0.ɵɵelementEnd();
462
+ i0.ɵɵelementStart(10, "div", 11)(11, "div", 12, 0);
463
+ i0.ɵɵprojection(13);
412
464
  i0.ɵɵelementEnd()()();
413
465
  } if (rf & 2) {
414
466
  i0.ɵɵclassProp("mj-forms-panel--related", ctx.Variant === "related-entity")("mj-forms-panel--inherited", ctx.Variant === "inherited");
415
467
  i0.ɵɵattribute("data-section-key", ctx.SectionKey);
416
- i0.ɵɵadvance(2);
468
+ i0.ɵɵadvance();
469
+ i0.ɵɵclassProp("mj-forms-panel-header--static", !ctx.Collapsible);
470
+ i0.ɵɵattribute("role", ctx.Collapsible ? "button" : null)("tabindex", ctx.Collapsible ? 0 : null);
471
+ i0.ɵɵadvance();
417
472
  i0.ɵɵconditional(ctx.ReorderAllowed ? 2 : -1);
418
473
  i0.ɵɵadvance(2);
419
474
  i0.ɵɵclassMap(ctx.Icon);
@@ -423,17 +478,17 @@ export class MjCollapsiblePanelComponent {
423
478
  i0.ɵɵconditional(ctx.BadgeCount !== undefined ? 7 : -1);
424
479
  i0.ɵɵadvance();
425
480
  i0.ɵɵconditional(ctx.Variant === "inherited" && ctx.InheritedFromEntity ? 8 : -1);
426
- i0.ɵɵadvance(2);
427
- i0.ɵɵclassMap(ctx.Expanded ? "fa fa-chevron-up" : "fa fa-chevron-down");
481
+ i0.ɵɵadvance();
482
+ i0.ɵɵconditional(ctx.Collapsible ? 9 : -1);
428
483
  i0.ɵɵadvance();
429
484
  i0.ɵɵclassProp("mj-forms-panel-body--collapsed", !ctx.Expanded);
430
485
  i0.ɵɵadvance();
431
486
  i0.ɵɵstyleProp("height", ctx.PanelContentHeight, "px");
432
- } }, styles: ["mj-collapsible-panel {\n display: block;\n}\n\nmj-collapsible-panel.mj-search-hidden {\n display: none;\n}\n\nmj-collapsible-panel.mj-drag-over {\n border: 2px dashed var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n}\n\n/* ============================================\n PANEL CARD\n ============================================ */\n.mj-forms-panel {\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-default);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n/* ============================================\n HEADER\n ============================================ */\n.mj-forms-panel-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n background: var(--mj-bg-surface-elevated);\n border-bottom: 2px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n transition: all 0.3s ease;\n}\n\n.mj-forms-panel-header:hover {\n background: var(--mj-bg-surface-hover);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n/* Drag handle */\n.mj-forms-drag-handle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0;\n height: 24px;\n color: var(--mj-text-muted);\n cursor: grab;\n opacity: 0;\n overflow: hidden;\n transition: width var(--mj-transition-base) ease, opacity var(--mj-transition-base) ease;\n flex-shrink: 0;\n}\n\n.mj-forms-panel-header:hover .mj-forms-drag-handle {\n width: 24px;\n opacity: 1;\n}\n\n.mj-forms-drag-handle:hover {\n color: var(--mj-brand-primary);\n}\n\n.mj-forms-drag-handle:active {\n cursor: grabbing;\n}\n\nmj-collapsible-panel.mj-dragging .mj-forms-drag-handle {\n width: 24px;\n opacity: 1;\n color: var(--mj-brand-primary);\n}\n\n/* Title group */\n.mj-forms-panel-title-group {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n}\n\n.mj-forms-panel-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n width: 24px;\n text-align: center;\n}\n\n.mj-forms-panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mj-forms-panel-chevron {\n color: var(--mj-text-secondary);\n font-size: 14px;\n transition: transform 0.3s ease;\n padding: 4px;\n}\n\n/* Row count badge */\n.mj-forms-row-count-badge {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n font-size: 12px;\n font-weight: 600;\n margin-left: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n line-height: 1;\n}\n\n.mj-forms-row-count-badge--zero {\n background: var(--mj-text-muted);\n}\n\n/* ============================================\n INHERITED VARIANT (IS-A parent fields)\n ============================================ */\n.mj-forms-panel--inherited {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-header {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-elevated));\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface-elevated));\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-icon {\n color: var(--mj-brand-primary);\n}\n\n.mj-forms-inherited-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 600;\n padding: 3px 10px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n cursor: pointer;\n transition: all var(--mj-transition-base) ease;\n text-decoration: none;\n}\n\n.mj-forms-inherited-badge:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.mj-forms-inherited-badge i {\n font-size: 10px;\n}\n\n/* ============================================\n RELATED ENTITY VARIANT\n ============================================ */\n.mj-forms-panel--related {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.mj-forms-panel--related .mj-forms-panel-header {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-elevated));\n}\n\n.mj-forms-panel--related .mj-forms-panel-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface-elevated));\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.mj-forms-panel--related .mj-forms-panel-icon {\n color: var(--mj-brand-primary);\n}\n\n/* Related entity content \u2014 400px default, user can drag-resize vertically */\n.mj-forms-panel--related .mj-forms-panel-content {\n height: 400px;\n padding: 0;\n overflow: hidden;\n resize: vertical;\n min-height: 120px;\n max-height: 800px;\n}\n\n/* Ensure child chain fills the resizable content area */\n.mj-forms-panel--related .mj-forms-panel-content > *,\n.mj-forms-panel--related .mj-forms-panel-content > .ng-star-inserted {\n height: 100%;\n}\n\n.mj-forms-panel--related .mj-forms-panel-content > * > * {\n height: 100%;\n}\n\n/* Related entity panels need the body to not clip the resize handle */\n.mj-forms-panel--related .mj-forms-panel-body {\n overflow: visible;\n}\n\n/* ============================================\n BODY (collapsible)\n ============================================ */\n.mj-forms-panel-body {\n max-height: 2000px;\n overflow: hidden;\n transition: max-height 0.4s ease, padding 0.4s ease, opacity 0.3s ease;\n opacity: 1;\n}\n\n.mj-forms-panel-body--collapsed {\n max-height: 0;\n padding: 0;\n opacity: 0;\n}\n\n.mj-forms-panel-content {\n padding: 20px;\n overflow: auto;\n max-height: 600px;\n}\n\n/* ============================================\n SEARCH HIGHLIGHTING\n ============================================ */\n.mj-forms-panel-title ::ng-deep .mj-forms-search-highlight {\n background-color: var(--mj-color-warning-200, #fef08a);\n color: var(--mj-color-warning-800, #854d0e);\n padding: 0;\n border-radius: 2px;\n font-weight: 700;\n box-shadow: 0 0 0 2px var(--mj-color-warning-200, #fef08a);\n}\n"], encapsulation: 2, changeDetection: 0 });
487
+ } }, styles: ["mj-collapsible-panel {\n display: block;\n}\n\nmj-collapsible-panel.mj-search-hidden {\n display: none;\n}\n\nmj-collapsible-panel.mj-drag-over {\n border: 2px dashed var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n}\n\n/* ============================================\n PANEL CARD\n ============================================ */\n.mj-forms-panel {\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-default);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n/* ============================================\n HEADER\n ============================================ */\n.mj-forms-panel-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n background: var(--mj-bg-surface-elevated);\n border-bottom: 2px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n transition: all 0.3s ease;\n}\n\n.mj-forms-panel-header:hover {\n background: var(--mj-bg-surface-hover);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n/* Static header \u2014 sections locked open (Config.collapsibleSections === false) */\n.mj-forms-panel-header--static {\n cursor: default;\n}\n\n.mj-forms-panel-header--static:hover {\n background: var(--mj-bg-surface-elevated);\n border-bottom-color: var(--mj-border-default);\n}\n\n/* Drag handle */\n.mj-forms-drag-handle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0;\n height: 24px;\n color: var(--mj-text-muted);\n cursor: grab;\n opacity: 0;\n overflow: hidden;\n transition: width var(--mj-transition-base) ease, opacity var(--mj-transition-base) ease;\n flex-shrink: 0;\n}\n\n.mj-forms-panel-header:hover .mj-forms-drag-handle {\n width: 24px;\n opacity: 1;\n}\n\n.mj-forms-drag-handle:hover {\n color: var(--mj-brand-primary);\n}\n\n.mj-forms-drag-handle:active {\n cursor: grabbing;\n}\n\nmj-collapsible-panel.mj-dragging .mj-forms-drag-handle {\n width: 24px;\n opacity: 1;\n color: var(--mj-brand-primary);\n}\n\n/* Title group */\n.mj-forms-panel-title-group {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n}\n\n.mj-forms-panel-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n width: 24px;\n text-align: center;\n}\n\n.mj-forms-panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mj-forms-panel-chevron {\n color: var(--mj-text-secondary);\n font-size: 14px;\n transition: transform 0.3s ease;\n padding: 4px;\n}\n\n/* Row count badge */\n.mj-forms-row-count-badge {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n font-size: 12px;\n font-weight: 600;\n margin-left: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n line-height: 1;\n}\n\n.mj-forms-row-count-badge--zero {\n background: var(--mj-text-muted);\n}\n\n/* ============================================\n INHERITED VARIANT (IS-A parent fields)\n ============================================ */\n.mj-forms-panel--inherited {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-header {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-elevated));\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface-elevated));\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-icon {\n color: var(--mj-brand-primary);\n}\n\n.mj-forms-inherited-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 600;\n padding: 3px 10px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n cursor: pointer;\n transition: all var(--mj-transition-base) ease;\n text-decoration: none;\n}\n\n.mj-forms-inherited-badge:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.mj-forms-inherited-badge i {\n font-size: 10px;\n}\n\n/* ============================================\n RELATED ENTITY VARIANT\n ============================================ */\n.mj-forms-panel--related {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.mj-forms-panel--related .mj-forms-panel-header {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-elevated));\n}\n\n.mj-forms-panel--related .mj-forms-panel-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface-elevated));\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.mj-forms-panel--related .mj-forms-panel-icon {\n color: var(--mj-brand-primary);\n}\n\n/* Related entity content \u2014 400px default, user can drag-resize vertically */\n.mj-forms-panel--related .mj-forms-panel-content {\n height: 400px;\n padding: 0;\n overflow: hidden;\n resize: vertical;\n min-height: 120px;\n max-height: 800px;\n}\n\n/* Ensure child chain fills the resizable content area */\n.mj-forms-panel--related .mj-forms-panel-content > *,\n.mj-forms-panel--related .mj-forms-panel-content > .ng-star-inserted {\n height: 100%;\n}\n\n.mj-forms-panel--related .mj-forms-panel-content > * > * {\n height: 100%;\n}\n\n/* Related entity panels need the body to not clip the resize handle */\n.mj-forms-panel--related .mj-forms-panel-body {\n overflow: visible;\n}\n\n/* ============================================\n BODY (collapsible)\n ============================================ */\n.mj-forms-panel-body {\n max-height: 2000px;\n overflow: hidden;\n transition: max-height 0.4s ease, padding 0.4s ease, opacity 0.3s ease;\n opacity: 1;\n}\n\n.mj-forms-panel-body--collapsed {\n max-height: 0;\n padding: 0;\n opacity: 0;\n}\n\n.mj-forms-panel-content {\n padding: 20px;\n overflow: auto;\n max-height: 600px;\n}\n\n/* ============================================\n SEARCH HIGHLIGHTING\n ============================================ */\n.mj-forms-panel-title ::ng-deep .mj-forms-search-highlight {\n /* Muted, theme-aware highlight (semantic token) \u2014 consistent with the field\n label + FK dropdown highlights. Replaces the old bright-yellow primitive. */\n background-color: var(--mj-search-highlight-bg);\n color: var(--mj-search-highlight-text);\n border-radius: 2px;\n padding: 0 1px;\n font-weight: 600;\n}\n"], encapsulation: 2, changeDetection: 0 });
433
488
  }
434
489
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MjCollapsiblePanelComponent, [{
435
490
  type: Component,
436
- args: [{ standalone: false, selector: 'mj-collapsible-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"mj-forms-panel\"\n [class.mj-forms-panel--related]=\"Variant === 'related-entity'\"\n [class.mj-forms-panel--inherited]=\"Variant === 'inherited'\"\n [attr.data-section-key]=\"SectionKey\">\n\n <!-- Panel Header -->\n <div class=\"mj-forms-panel-header\" role=\"button\" tabindex=\"0\" (click)=\"Toggle()\">\n <!-- Drag Handle (hidden when reorder disabled) -->\n @if (ReorderAllowed) {\n <div class=\"mj-forms-drag-handle\"\n title=\"Drag to reorder sections\"\n draggable=\"true\"\n (dragstart)=\"OnDragStart($event)\"\n (dragend)=\"OnDragEnd()\"\n (click)=\"$event.stopPropagation()\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n }\n\n <!-- Icon + Title -->\n <div class=\"mj-forms-panel-title-group\">\n <i [class]=\"Icon\" class=\"mj-forms-panel-icon\"></i>\n <h3 class=\"mj-forms-panel-title\">\n <span [innerHTML]=\"DisplayName\"></span>\n <!-- Row count badge for related entities -->\n @if (BadgeCount !== undefined) {\n <span class=\"mj-forms-row-count-badge\" [class.mj-forms-row-count-badge--zero]=\"BadgeCount === 0\">\n {{ BadgeCount }}\n </span>\n }\n </h3>\n </div>\n\n <!-- Inherited From badge (IS-A) -->\n @if (Variant === 'inherited' && InheritedFromEntity) {\n <a class=\"mj-forms-inherited-badge\" (click)=\"OnInheritedBadgeClick($event)\"\n [title]=\"'View parent record: ' + InheritedFromEntity\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n Inherited from {{ InheritedFromEntity }}\n </a>\n }\n\n <!-- Chevron -->\n <div class=\"mj-forms-panel-chevron\">\n <i [class]=\"Expanded ? 'fa fa-chevron-up' : 'fa fa-chevron-down'\"></i>\n </div>\n </div>\n\n <!-- Panel Body -->\n <div class=\"mj-forms-panel-body\" [class.mj-forms-panel-body--collapsed]=\"!Expanded\">\n <div class=\"mj-forms-panel-content\"\n #panelContent\n [style.height.px]=\"PanelContentHeight\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", styles: ["mj-collapsible-panel {\n display: block;\n}\n\nmj-collapsible-panel.mj-search-hidden {\n display: none;\n}\n\nmj-collapsible-panel.mj-drag-over {\n border: 2px dashed var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n}\n\n/* ============================================\n PANEL CARD\n ============================================ */\n.mj-forms-panel {\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-default);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n/* ============================================\n HEADER\n ============================================ */\n.mj-forms-panel-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n background: var(--mj-bg-surface-elevated);\n border-bottom: 2px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n transition: all 0.3s ease;\n}\n\n.mj-forms-panel-header:hover {\n background: var(--mj-bg-surface-hover);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n/* Drag handle */\n.mj-forms-drag-handle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0;\n height: 24px;\n color: var(--mj-text-muted);\n cursor: grab;\n opacity: 0;\n overflow: hidden;\n transition: width var(--mj-transition-base) ease, opacity var(--mj-transition-base) ease;\n flex-shrink: 0;\n}\n\n.mj-forms-panel-header:hover .mj-forms-drag-handle {\n width: 24px;\n opacity: 1;\n}\n\n.mj-forms-drag-handle:hover {\n color: var(--mj-brand-primary);\n}\n\n.mj-forms-drag-handle:active {\n cursor: grabbing;\n}\n\nmj-collapsible-panel.mj-dragging .mj-forms-drag-handle {\n width: 24px;\n opacity: 1;\n color: var(--mj-brand-primary);\n}\n\n/* Title group */\n.mj-forms-panel-title-group {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n}\n\n.mj-forms-panel-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n width: 24px;\n text-align: center;\n}\n\n.mj-forms-panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mj-forms-panel-chevron {\n color: var(--mj-text-secondary);\n font-size: 14px;\n transition: transform 0.3s ease;\n padding: 4px;\n}\n\n/* Row count badge */\n.mj-forms-row-count-badge {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n font-size: 12px;\n font-weight: 600;\n margin-left: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n line-height: 1;\n}\n\n.mj-forms-row-count-badge--zero {\n background: var(--mj-text-muted);\n}\n\n/* ============================================\n INHERITED VARIANT (IS-A parent fields)\n ============================================ */\n.mj-forms-panel--inherited {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-header {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-elevated));\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface-elevated));\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-icon {\n color: var(--mj-brand-primary);\n}\n\n.mj-forms-inherited-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 600;\n padding: 3px 10px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n cursor: pointer;\n transition: all var(--mj-transition-base) ease;\n text-decoration: none;\n}\n\n.mj-forms-inherited-badge:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.mj-forms-inherited-badge i {\n font-size: 10px;\n}\n\n/* ============================================\n RELATED ENTITY VARIANT\n ============================================ */\n.mj-forms-panel--related {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.mj-forms-panel--related .mj-forms-panel-header {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-elevated));\n}\n\n.mj-forms-panel--related .mj-forms-panel-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface-elevated));\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.mj-forms-panel--related .mj-forms-panel-icon {\n color: var(--mj-brand-primary);\n}\n\n/* Related entity content \u2014 400px default, user can drag-resize vertically */\n.mj-forms-panel--related .mj-forms-panel-content {\n height: 400px;\n padding: 0;\n overflow: hidden;\n resize: vertical;\n min-height: 120px;\n max-height: 800px;\n}\n\n/* Ensure child chain fills the resizable content area */\n.mj-forms-panel--related .mj-forms-panel-content > *,\n.mj-forms-panel--related .mj-forms-panel-content > .ng-star-inserted {\n height: 100%;\n}\n\n.mj-forms-panel--related .mj-forms-panel-content > * > * {\n height: 100%;\n}\n\n/* Related entity panels need the body to not clip the resize handle */\n.mj-forms-panel--related .mj-forms-panel-body {\n overflow: visible;\n}\n\n/* ============================================\n BODY (collapsible)\n ============================================ */\n.mj-forms-panel-body {\n max-height: 2000px;\n overflow: hidden;\n transition: max-height 0.4s ease, padding 0.4s ease, opacity 0.3s ease;\n opacity: 1;\n}\n\n.mj-forms-panel-body--collapsed {\n max-height: 0;\n padding: 0;\n opacity: 0;\n}\n\n.mj-forms-panel-content {\n padding: 20px;\n overflow: auto;\n max-height: 600px;\n}\n\n/* ============================================\n SEARCH HIGHLIGHTING\n ============================================ */\n.mj-forms-panel-title ::ng-deep .mj-forms-search-highlight {\n background-color: var(--mj-color-warning-200, #fef08a);\n color: var(--mj-color-warning-800, #854d0e);\n padding: 0;\n border-radius: 2px;\n font-weight: 700;\n box-shadow: 0 0 0 2px var(--mj-color-warning-200, #fef08a);\n}\n"] }]
491
+ args: [{ standalone: false, selector: 'mj-collapsible-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"mj-forms-panel\"\n [class.mj-forms-panel--related]=\"Variant === 'related-entity'\"\n [class.mj-forms-panel--inherited]=\"Variant === 'inherited'\"\n [attr.data-section-key]=\"SectionKey\">\n\n <!-- Panel Header -->\n <div class=\"mj-forms-panel-header\"\n [class.mj-forms-panel-header--static]=\"!Collapsible\"\n [attr.role]=\"Collapsible ? 'button' : null\"\n [attr.tabindex]=\"Collapsible ? 0 : null\"\n (click)=\"Toggle()\">\n <!-- Drag Handle (hidden when reorder disabled) -->\n @if (ReorderAllowed) {\n <div class=\"mj-forms-drag-handle\"\n title=\"Drag to reorder sections\"\n draggable=\"true\"\n (dragstart)=\"OnDragStart($event)\"\n (dragend)=\"OnDragEnd()\"\n (click)=\"$event.stopPropagation()\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n }\n\n <!-- Icon + Title -->\n <div class=\"mj-forms-panel-title-group\">\n <i [class]=\"Icon\" class=\"mj-forms-panel-icon\"></i>\n <h3 class=\"mj-forms-panel-title\">\n <span [innerHTML]=\"DisplayName\"></span>\n <!-- Row count badge for related entities -->\n @if (BadgeCount !== undefined) {\n <span class=\"mj-forms-row-count-badge\" [class.mj-forms-row-count-badge--zero]=\"BadgeCount === 0\">\n {{ BadgeCount }}\n </span>\n }\n </h3>\n </div>\n\n <!-- Inherited From badge (IS-A) -->\n @if (Variant === 'inherited' && InheritedFromEntity) {\n <a class=\"mj-forms-inherited-badge\" (click)=\"OnInheritedBadgeClick($event)\"\n [title]=\"'View parent record: ' + InheritedFromEntity\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n Inherited from {{ InheritedFromEntity }}\n </a>\n }\n\n <!-- Chevron (hidden when sections are locked open) -->\n @if (Collapsible) {\n <div class=\"mj-forms-panel-chevron\">\n <i [class]=\"Expanded ? 'fa fa-chevron-up' : 'fa fa-chevron-down'\"></i>\n </div>\n }\n </div>\n\n <!-- Panel Body -->\n <div class=\"mj-forms-panel-body\" [class.mj-forms-panel-body--collapsed]=\"!Expanded\">\n <div class=\"mj-forms-panel-content\"\n #panelContent\n [style.height.px]=\"PanelContentHeight\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", styles: ["mj-collapsible-panel {\n display: block;\n}\n\nmj-collapsible-panel.mj-search-hidden {\n display: none;\n}\n\nmj-collapsible-panel.mj-drag-over {\n border: 2px dashed var(--mj-brand-primary);\n border-radius: var(--mj-radius-md);\n}\n\n/* ============================================\n PANEL CARD\n ============================================ */\n.mj-forms-panel {\n background: var(--mj-bg-surface-card);\n border-radius: var(--mj-radius-md);\n box-shadow: var(--mj-shadow-sm);\n border: 1px solid var(--mj-border-default);\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n/* ============================================\n HEADER\n ============================================ */\n.mj-forms-panel-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 16px 20px;\n background: var(--mj-bg-surface-elevated);\n border-bottom: 2px solid var(--mj-border-default);\n cursor: pointer;\n user-select: none;\n transition: all 0.3s ease;\n}\n\n.mj-forms-panel-header:hover {\n background: var(--mj-bg-surface-hover);\n border-bottom-color: var(--mj-brand-primary);\n}\n\n/* Static header \u2014 sections locked open (Config.collapsibleSections === false) */\n.mj-forms-panel-header--static {\n cursor: default;\n}\n\n.mj-forms-panel-header--static:hover {\n background: var(--mj-bg-surface-elevated);\n border-bottom-color: var(--mj-border-default);\n}\n\n/* Drag handle */\n.mj-forms-drag-handle {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 0;\n height: 24px;\n color: var(--mj-text-muted);\n cursor: grab;\n opacity: 0;\n overflow: hidden;\n transition: width var(--mj-transition-base) ease, opacity var(--mj-transition-base) ease;\n flex-shrink: 0;\n}\n\n.mj-forms-panel-header:hover .mj-forms-drag-handle {\n width: 24px;\n opacity: 1;\n}\n\n.mj-forms-drag-handle:hover {\n color: var(--mj-brand-primary);\n}\n\n.mj-forms-drag-handle:active {\n cursor: grabbing;\n}\n\nmj-collapsible-panel.mj-dragging .mj-forms-drag-handle {\n width: 24px;\n opacity: 1;\n color: var(--mj-brand-primary);\n}\n\n/* Title group */\n.mj-forms-panel-title-group {\n display: flex;\n align-items: center;\n gap: 12px;\n flex: 1;\n}\n\n.mj-forms-panel-icon {\n font-size: 18px;\n color: var(--mj-brand-primary);\n width: 24px;\n text-align: center;\n}\n\n.mj-forms-panel-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.mj-forms-panel-chevron {\n color: var(--mj-text-secondary);\n font-size: 14px;\n transition: transform 0.3s ease;\n padding: 4px;\n}\n\n/* Row count badge */\n.mj-forms-row-count-badge {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n padding: 2px 8px;\n border-radius: var(--mj-radius-full);\n font-size: 12px;\n font-weight: 600;\n margin-left: 8px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n line-height: 1;\n}\n\n.mj-forms-row-count-badge--zero {\n background: var(--mj-text-muted);\n}\n\n/* ============================================\n INHERITED VARIANT (IS-A parent fields)\n ============================================ */\n.mj-forms-panel--inherited {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-header {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-elevated));\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface-elevated));\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.mj-forms-panel--inherited .mj-forms-panel-icon {\n color: var(--mj-brand-primary);\n}\n\n.mj-forms-inherited-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 11px;\n font-weight: 600;\n padding: 3px 10px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n cursor: pointer;\n transition: all var(--mj-transition-base) ease;\n text-decoration: none;\n}\n\n.mj-forms-inherited-badge:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 20%, transparent);\n}\n\n.mj-forms-inherited-badge i {\n font-size: 10px;\n}\n\n/* ============================================\n RELATED ENTITY VARIANT\n ============================================ */\n.mj-forms-panel--related {\n border-left: 3px solid var(--mj-brand-primary);\n}\n\n.mj-forms-panel--related .mj-forms-panel-header {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface-elevated));\n}\n\n.mj-forms-panel--related .mj-forms-panel-header:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 14%, var(--mj-bg-surface-elevated));\n border-bottom-color: var(--mj-brand-primary);\n}\n\n.mj-forms-panel--related .mj-forms-panel-icon {\n color: var(--mj-brand-primary);\n}\n\n/* Related entity content \u2014 400px default, user can drag-resize vertically */\n.mj-forms-panel--related .mj-forms-panel-content {\n height: 400px;\n padding: 0;\n overflow: hidden;\n resize: vertical;\n min-height: 120px;\n max-height: 800px;\n}\n\n/* Ensure child chain fills the resizable content area */\n.mj-forms-panel--related .mj-forms-panel-content > *,\n.mj-forms-panel--related .mj-forms-panel-content > .ng-star-inserted {\n height: 100%;\n}\n\n.mj-forms-panel--related .mj-forms-panel-content > * > * {\n height: 100%;\n}\n\n/* Related entity panels need the body to not clip the resize handle */\n.mj-forms-panel--related .mj-forms-panel-body {\n overflow: visible;\n}\n\n/* ============================================\n BODY (collapsible)\n ============================================ */\n.mj-forms-panel-body {\n max-height: 2000px;\n overflow: hidden;\n transition: max-height 0.4s ease, padding 0.4s ease, opacity 0.3s ease;\n opacity: 1;\n}\n\n.mj-forms-panel-body--collapsed {\n max-height: 0;\n padding: 0;\n opacity: 0;\n}\n\n.mj-forms-panel-content {\n padding: 20px;\n overflow: auto;\n max-height: 600px;\n}\n\n/* ============================================\n SEARCH HIGHLIGHTING\n ============================================ */\n.mj-forms-panel-title ::ng-deep .mj-forms-search-highlight {\n /* Muted, theme-aware highlight (semantic token) \u2014 consistent with the field\n label + FK dropdown highlights. Replaces the old bright-yellow primitive. */\n background-color: var(--mj-search-highlight-bg);\n color: var(--mj-search-highlight-text);\n border-radius: 2px;\n padding: 0 1px;\n font-weight: 600;\n}\n"] }]
437
492
  }], null, { SectionKey: [{
438
493
  type: Input
439
494
  }], SectionName: [{
@@ -454,6 +509,8 @@ export class MjCollapsiblePanelComponent {
454
509
  type: Input
455
510
  }], InheritedRecordPrimaryKey: [{
456
511
  type: Input
512
+ }], Hidden: [{
513
+ type: Input
457
514
  }], _deprecatedSectionKey: [{
458
515
  type: Input,
459
516
  args: ['sectionKey']
@@ -499,5 +556,5 @@ export class MjCollapsiblePanelComponent {
499
556
  type: HostListener,
500
557
  args: ['drop', ['$event']]
501
558
  }] }); })();
502
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MjCollapsiblePanelComponent, { className: "MjCollapsiblePanelComponent", filePath: "src/lib/panel/collapsible-panel.component.ts", lineNumber: 54 }); })();
559
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MjCollapsiblePanelComponent, { className: "MjCollapsiblePanelComponent", filePath: "src/lib/panel/collapsible-panel.component.ts", lineNumber: 55 }); })();
503
560
  //# sourceMappingURL=collapsible-panel.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible-panel.component.js","sourceRoot":"","sources":["../../../src/lib/panel/collapsible-panel.component.ts","../../../src/lib/panel/collapsible-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component, Input, Output, EventEmitter,\n ChangeDetectionStrategy, ChangeDetectorRef, inject,\n OnChanges, SimpleChanges, OnInit, AfterContentInit, AfterViewInit, OnDestroy,\n ContentChildren, QueryList, HostBinding, HostListener, ElementRef,\n ViewChild, NgZone, ViewEncapsulation\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { FormContext, PanelVariant, PanelDragStartEvent, PanelDropEvent } from '../types/form-types';\nimport { FormNavigationEvent } from '../types/navigation-events';\nimport { MjFormFieldComponent } from '../field/form-field.component';\nimport { CompositeKey } from '@memberjunction/core';\nimport { EscapeHTML, HighlightSearchMatches } from '@memberjunction/global';\n\n/**\n * Reusable collapsible panel for form sections.\n *\n * Supports three visual variants:\n * - **default**: White card with accent border (standard field sections)\n * - **related-entity**: Blue-accented card with row count badge (related entity grids)\n * - **inherited**: Purple-accented card with \"Inherited from X\" badge (IS-A parent field sections)\n *\n * Features:\n * - Expand/collapse with smooth animation\n * - Search filtering (hides non-matching panels, highlights matched names)\n * - Drag-to-reorder sections\n * - Inheritable \"Inherited from X\" badge with navigation event\n * - Row count badge for related entity sections\n *\n * @example\n * ```html\n * <mj-collapsible-panel\n * SectionKey=\"productDetails\"\n * SectionName=\"Product Details\"\n * Icon=\"fa fa-box\"\n * Variant=\"inherited\"\n * InheritedFromEntity=\"Products\"\n * [Form]=\"formComponent\"\n * [FormContext]=\"formContext\"\n * (Navigate)=\"onNavigate($event)\">\n * <mj-form-field ...></mj-form-field>\n * </mj-collapsible-panel>\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-collapsible-panel',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None, // Required to style projected content (grids, etc.)\n templateUrl: './collapsible-panel.component.html',\n styleUrls: ['./collapsible-panel.component.css']\n})\nexport class MjCollapsiblePanelComponent implements OnInit, OnChanges, AfterContentInit, AfterViewInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private elementRef = inject(ElementRef);\n private ngZone = inject(NgZone);\n\n /** Unique key for state persistence */\n @Input() SectionKey = '';\n\n /** Display name shown in the panel header */\n @Input() SectionName = '';\n\n /** Font Awesome icon class for the panel header */\n @Input() Icon = 'fa fa-folder';\n\n /**\n * Reference to the parent form component for state delegation.\n * Expected to have IsSectionExpanded, SetSectionExpanded, getSectionDisplayOrder methods.\n */\n @Input() Form: unknown;\n\n /** Form-level context (search filter, showEmptyFields) */\n @Input() FormContext?: FormContext;\n\n /** Panel visual variant */\n @Input() Variant: PanelVariant = 'default';\n\n /** Row count badge for related entity sections */\n @Input() BadgeCount: number | undefined;\n\n /** Default expanded state when no persisted state exists */\n @Input() DefaultExpanded: boolean | undefined;\n\n /**\n * For 'inherited' variant: the parent entity name this section's fields come from.\n * Displayed as \"Inherited from X\" badge and used for navigation.\n */\n @Input() InheritedFromEntity = '';\n\n /**\n * For 'inherited' variant: the primary key to navigate to when clicking the badge.\n * (Shared PK in IS-A relationships.)\n */\n @Input() InheritedRecordPrimaryKey?: CompositeKey;\n\n // ---- Deprecated camelCase aliases (backward compat) ----\n\n /** @deprecated Use [SectionKey] instead */\n @Input('sectionKey') set _deprecatedSectionKey(value: string) { this.SectionKey = value; }\n\n /** @deprecated Use [SectionName] instead */\n @Input('sectionName') set _deprecatedSectionName(value: string) { this.SectionName = value; }\n\n /** @deprecated Use [Icon] instead */\n @Input('icon') set _deprecatedIcon(value: string) { this.Icon = value; }\n\n /** @deprecated Use [Form] instead */\n @Input('form') set _deprecatedForm(value: unknown) { this.Form = value; }\n\n /** @deprecated Use [FormContext] instead */\n @Input('formContext') set _deprecatedFormContext(value: FormContext | undefined) { this.FormContext = value; }\n\n // ---- Outputs ----\n\n @Output() DragStarted = new EventEmitter<PanelDragStartEvent>();\n @Output() DragEnded = new EventEmitter<void>();\n @Output() PanelDrop = new EventEmitter<PanelDropEvent>();\n @Output() Navigate = new EventEmitter<FormNavigationEvent>();\n\n // ---- Content Children ----\n\n @ContentChildren(MjFormFieldComponent, { descendants: true }) FieldComponents!: QueryList<MjFormFieldComponent>;\n\n // ---- State ----\n\n DisplayName = '';\n FieldNames = '';\n IsVisible = true;\n\n @HostBinding('class')\n get HostClass(): string {\n const classes = [`mj-panel--${this.Variant}`];\n if (!this.IsVisible) classes.push('mj-search-hidden');\n if (this.IsDragging) classes.push('mj-dragging');\n if (this.IsDragOver) classes.push('mj-drag-over');\n return classes.join(' ');\n }\n\n @HostBinding('style.order')\n get CssOrder(): number {\n const formRef = this.Form as { getSectionDisplayOrder?: (key: string) => number };\n return formRef?.getSectionDisplayOrder ? formRef.getSectionDisplayOrder(this.SectionKey) : 0;\n }\n\n IsDragging = false;\n IsDragOver = false;\n\n // ---- Event relay ----\n\n /** Signals re-subscription when ContentChildren change */\n private fieldNavReset$ = new Subject<void>();\n\n // ---- Panel content resize ----\n\n @ViewChild('panelContent') private panelContentRef?: ElementRef<HTMLElement>;\n private resizeObserver?: ResizeObserver;\n private resizeDebounceTimer?: ReturnType<typeof setTimeout>;\n /** ResizeObserver fires once synchronously on observe(); that initial measurement is not a user resize. */\n private resizeObserverPrimed = false;\n\n /**\n * Persisted panel height for related-entity panels.\n * Returns undefined to let CSS default (400px) apply.\n */\n get PanelContentHeight(): number | undefined {\n if (this.Variant !== 'related-entity') return undefined;\n const formRef = this.Form as { GetSectionPanelHeight?: (key: string) => number | undefined };\n return formRef?.GetSectionPanelHeight?.(this.SectionKey);\n }\n\n /** Whether drag-to-reorder is allowed (from FormContext) */\n get ReorderAllowed(): boolean {\n return this.FormContext?.allowSectionReorder !== false;\n }\n\n /** Whether the panel is expanded (delegates to form state) */\n get Expanded(): boolean {\n const formRef = this.Form as { IsSectionExpanded?: (key: string, defaultExpanded?: boolean) => boolean };\n return formRef?.IsSectionExpanded ? formRef.IsSectionExpanded(this.SectionKey, this.DefaultExpanded) : true;\n }\n\n // ---- Lifecycle ----\n\n ngOnInit(): void {\n this.DisplayName = this.SectionName;\n }\n\n ngAfterContentInit(): void {\n this.UpdateFieldNames();\n this.SubscribeToFieldNavigateEvents();\n this.FieldComponents.changes.subscribe(() => {\n this.UpdateFieldNames();\n this.SubscribeToFieldNavigateEvents();\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['SectionName']) {\n this.DisplayName = this.SectionName;\n }\n if (changes['SectionName'] || changes['FormContext']) {\n this.UpdateVisibilityAndHighlighting();\n }\n if (changes['FormContext'] && this.FieldComponents) {\n this.FieldComponents.forEach(field => {\n field.FormContext = this.FormContext;\n });\n }\n }\n\n ngAfterViewInit(): void {\n this.SetupResizeObserver();\n }\n\n ngOnDestroy(): void {\n this.fieldNavReset$.next();\n this.fieldNavReset$.complete();\n this.resizeObserver?.disconnect();\n if (this.resizeDebounceTimer) {\n clearTimeout(this.resizeDebounceTimer);\n }\n }\n\n // ---- Actions ----\n\n Toggle(): void {\n const formRef = this.Form as { SetSectionExpanded?: (key: string, expanded: boolean) => void };\n if (formRef?.SetSectionExpanded) {\n formRef.SetSectionExpanded(this.SectionKey, !this.Expanded);\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Navigate to the parent entity when clicking the \"Inherited from X\" badge.\n * Derives the PrimaryKey from the Form's record when InheritedRecordPrimaryKey\n * is not explicitly provided (which is the common case in generated templates).\n */\n OnInheritedBadgeClick(event: MouseEvent): void {\n event.stopPropagation();\n if (!this.InheritedFromEntity) return;\n\n const primaryKey = this.InheritedRecordPrimaryKey\n ?? (this.Form as { record?: { PrimaryKey: CompositeKey } })?.record?.PrimaryKey\n ?? new CompositeKey([]);\n\n this.Navigate.emit({\n Kind: 'entity-hierarchy',\n EntityName: this.InheritedFromEntity,\n PrimaryKey: primaryKey,\n Direction: 'parent'\n });\n }\n\n // ---- Drag and Drop ----\n\n @HostListener('dragover', ['$event'])\n OnDragOver(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n event.stopPropagation();\n if (event.dataTransfer?.types.includes('text/plain')) {\n this.IsDragOver = true;\n }\n }\n\n @HostListener('dragleave', ['$event'])\n OnDragLeave(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n this.IsDragOver = false;\n }\n\n @HostListener('drop', ['$event'])\n OnDrop(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n event.stopPropagation();\n this.IsDragOver = false;\n\n const sourceSectionKey = event.dataTransfer?.getData('text/plain');\n if (sourceSectionKey && sourceSectionKey !== this.SectionKey) {\n this.PanelDrop.emit({\n SourceSectionKey: sourceSectionKey,\n TargetSectionKey: this.SectionKey\n });\n this.ReorderSections(sourceSectionKey, this.SectionKey);\n }\n }\n\n OnDragStart(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n this.IsDragging = true;\n event.dataTransfer?.setData('text/plain', this.SectionKey);\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n }\n this.DragStarted.emit({ SectionKey: this.SectionKey, Event: event });\n }\n\n OnDragEnd(): void {\n this.IsDragging = false;\n this.DragEnded.emit();\n }\n\n // ---- Private Methods ----\n\n private ReorderSections(sourceSectionKey: string, targetSectionKey: string): void {\n const formRef = this.Form as {\n getSectionOrder?: () => string[];\n setSectionOrder?: (order: string[]) => void;\n };\n if (!formRef?.getSectionOrder || !formRef?.setSectionOrder) return;\n\n const currentOrder = formRef.getSectionOrder();\n const sourceIndex = currentOrder.indexOf(sourceSectionKey);\n const targetIndex = currentOrder.indexOf(targetSectionKey);\n if (sourceIndex === -1 || targetIndex === -1) return;\n\n const newOrder = [...currentOrder];\n newOrder.splice(sourceIndex, 1);\n newOrder.splice(targetIndex, 0, sourceSectionKey);\n formRef.setSectionOrder(newOrder);\n this.cdr.markForCheck();\n }\n\n private UpdateFieldNames(): void {\n if (this.FieldComponents) {\n const names: string[] = [];\n this.FieldComponents.forEach(field => {\n if (field.DisplayName) {\n names.push(field.DisplayName.toLowerCase());\n }\n });\n this.FieldNames = names.join(' ');\n this.UpdateVisibilityAndHighlighting();\n }\n }\n\n /**\n * Subscribes to Navigate events from all child form-field components\n * and relays them through this panel's Navigate output.\n */\n private SubscribeToFieldNavigateEvents(): void {\n this.fieldNavReset$.next(); // tear down previous subscriptions\n this.FieldComponents.forEach(field => {\n field.Navigate.pipe(takeUntil(this.fieldNavReset$)).subscribe((event: FormNavigationEvent) => {\n this.Navigate.emit(event);\n });\n });\n }\n\n /**\n * Sets up a ResizeObserver on the panel content div for related-entity panels.\n * When the user drags the CSS resize handle, we persist the new height.\n */\n private SetupResizeObserver(): void {\n if (this.Variant !== 'related-entity' || !this.panelContentRef) return;\n\n const el = this.panelContentRef.nativeElement;\n // Run outside Angular zone to avoid triggering change detection on every resize frame\n this.ngZone.runOutsideAngular(() => {\n this.resizeObserver = new ResizeObserver((entries) => {\n // Skip the synchronous initial fire emitted when observe() is called — it's the\n // panel's own first measurement on load, not a user-initiated resize. Persisting\n // it would write a spurious panelHeight for every panel on form open.\n if (!this.resizeObserverPrimed) {\n this.resizeObserverPrimed = true;\n return;\n }\n // Only a height change while the panel is expanded reflects a genuine user drag of\n // the resize handle. Ignore reflows while collapsed (e.g. content settling on load).\n if (!this.Expanded) return;\n const entry = entries[0];\n if (!entry) return;\n const newHeight = Math.round(entry.contentRect.height);\n this.DebouncePersistHeight(newHeight);\n });\n this.resizeObserver.observe(el);\n });\n }\n\n /**\n * Debounces height persistence so we don't write to DB on every resize frame.\n */\n private DebouncePersistHeight(height: number): void {\n if (this.resizeDebounceTimer) {\n clearTimeout(this.resizeDebounceTimer);\n }\n this.resizeDebounceTimer = setTimeout(() => {\n const formRef = this.Form as { SetSectionPanelHeight?: (key: string, height: number) => void };\n formRef?.SetSectionPanelHeight?.(this.SectionKey, height);\n }, 500);\n }\n\n private UpdateVisibilityAndHighlighting(): void {\n const searchTerm = (this.FormContext?.sectionFilter || '').toLowerCase().trim();\n\n if (!searchTerm) {\n this.IsVisible = true;\n this.DisplayName = this.SectionName;\n this.cdr.markForCheck();\n return;\n }\n\n const sectionMatches = this.SectionName.toLowerCase().includes(searchTerm);\n const fieldsMatch = this.FieldNames.includes(searchTerm);\n this.IsVisible = sectionMatches || fieldsMatch;\n\n // DisplayName is bound to `[innerHTML]` in the template — must always be HTML-safe.\n this.DisplayName =\n this.IsVisible && sectionMatches\n ? HighlightSearchMatches(this.SectionName, searchTerm, 'mj-forms-search-highlight')\n : EscapeHTML(this.SectionName);\n\n this.cdr.markForCheck();\n }\n}\n","<div class=\"mj-forms-panel\"\n [class.mj-forms-panel--related]=\"Variant === 'related-entity'\"\n [class.mj-forms-panel--inherited]=\"Variant === 'inherited'\"\n [attr.data-section-key]=\"SectionKey\">\n\n <!-- Panel Header -->\n <div class=\"mj-forms-panel-header\" role=\"button\" tabindex=\"0\" (click)=\"Toggle()\">\n <!-- Drag Handle (hidden when reorder disabled) -->\n @if (ReorderAllowed) {\n <div class=\"mj-forms-drag-handle\"\n title=\"Drag to reorder sections\"\n draggable=\"true\"\n (dragstart)=\"OnDragStart($event)\"\n (dragend)=\"OnDragEnd()\"\n (click)=\"$event.stopPropagation()\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n }\n\n <!-- Icon + Title -->\n <div class=\"mj-forms-panel-title-group\">\n <i [class]=\"Icon\" class=\"mj-forms-panel-icon\"></i>\n <h3 class=\"mj-forms-panel-title\">\n <span [innerHTML]=\"DisplayName\"></span>\n <!-- Row count badge for related entities -->\n @if (BadgeCount !== undefined) {\n <span class=\"mj-forms-row-count-badge\" [class.mj-forms-row-count-badge--zero]=\"BadgeCount === 0\">\n {{ BadgeCount }}\n </span>\n }\n </h3>\n </div>\n\n <!-- Inherited From badge (IS-A) -->\n @if (Variant === 'inherited' && InheritedFromEntity) {\n <a class=\"mj-forms-inherited-badge\" (click)=\"OnInheritedBadgeClick($event)\"\n [title]=\"'View parent record: ' + InheritedFromEntity\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n Inherited from {{ InheritedFromEntity }}\n </a>\n }\n\n <!-- Chevron -->\n <div class=\"mj-forms-panel-chevron\">\n <i [class]=\"Expanded ? 'fa fa-chevron-up' : 'fa fa-chevron-down'\"></i>\n </div>\n </div>\n\n <!-- Panel Body -->\n <div class=\"mj-forms-panel-body\" [class.mj-forms-panel-body--collapsed]=\"!Expanded\">\n <div class=\"mj-forms-panel-content\"\n #panelContent\n [style.height.px]=\"PanelContentHeight\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n"]}
1
+ {"version":3,"file":"collapsible-panel.component.js","sourceRoot":"","sources":["../../../src/lib/panel/collapsible-panel.component.ts","../../../src/lib/panel/collapsible-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component, Input, Output, EventEmitter,\n ChangeDetectionStrategy, ChangeDetectorRef, inject,\n OnChanges, SimpleChanges, OnInit, AfterContentInit, AfterViewInit, OnDestroy,\n ContentChildren, QueryList, HostBinding, HostListener, ElementRef,\n ViewChild, NgZone, ViewEncapsulation\n} from '@angular/core';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { FormContext, PanelVariant, PanelDragStartEvent, PanelDropEvent } from '../types/form-types';\nimport { IsFormSectionHidden } from '../types/entity-form-config';\nimport { FormNavigationEvent } from '../types/navigation-events';\nimport { MjFormFieldComponent } from '../field/form-field.component';\nimport { CompositeKey } from '@memberjunction/core';\nimport { EscapeHTML, HighlightSearchMatches } from '@memberjunction/global';\n\n/**\n * Reusable collapsible panel for form sections.\n *\n * Supports three visual variants:\n * - **default**: White card with accent border (standard field sections)\n * - **related-entity**: Blue-accented card with row count badge (related entity grids)\n * - **inherited**: Purple-accented card with \"Inherited from X\" badge (IS-A parent field sections)\n *\n * Features:\n * - Expand/collapse with smooth animation\n * - Search filtering (hides non-matching panels, highlights matched names)\n * - Drag-to-reorder sections\n * - Inheritable \"Inherited from X\" badge with navigation event\n * - Row count badge for related entity sections\n *\n * @example\n * ```html\n * <mj-collapsible-panel\n * SectionKey=\"productDetails\"\n * SectionName=\"Product Details\"\n * Icon=\"fa fa-box\"\n * Variant=\"inherited\"\n * InheritedFromEntity=\"Products\"\n * [Form]=\"formComponent\"\n * [FormContext]=\"formContext\"\n * (Navigate)=\"onNavigate($event)\">\n * <mj-form-field ...></mj-form-field>\n * </mj-collapsible-panel>\n * ```\n */\n@Component({\n standalone: false,\n selector: 'mj-collapsible-panel',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None, // Required to style projected content (grids, etc.)\n templateUrl: './collapsible-panel.component.html',\n styleUrls: ['./collapsible-panel.component.css']\n})\nexport class MjCollapsiblePanelComponent implements OnInit, OnChanges, AfterContentInit, AfterViewInit, OnDestroy {\n private cdr = inject(ChangeDetectorRef);\n private elementRef = inject(ElementRef);\n private ngZone = inject(NgZone);\n\n /** Unique key for state persistence */\n @Input() SectionKey = '';\n\n /** Display name shown in the panel header */\n @Input() SectionName = '';\n\n /** Font Awesome icon class for the panel header */\n @Input() Icon = 'fa fa-folder';\n\n /**\n * Reference to the parent form component for state delegation.\n * Expected to have IsSectionExpanded, SetSectionExpanded, getSectionDisplayOrder methods.\n */\n @Input() Form: unknown;\n\n /** Form-level context (search filter, showEmptyFields) */\n @Input() FormContext?: FormContext;\n\n /** Panel visual variant */\n @Input() Variant: PanelVariant = 'default';\n\n /** Row count badge for related entity sections */\n @Input() BadgeCount: number | undefined;\n\n /** Default expanded state when no persisted state exists */\n @Input() DefaultExpanded: boolean | undefined;\n\n /**\n * For 'inherited' variant: the parent entity name this section's fields come from.\n * Displayed as \"Inherited from X\" badge and used for navigation.\n */\n @Input() InheritedFromEntity = '';\n\n /**\n * For 'inherited' variant: the primary key to navigate to when clicking the badge.\n * (Shared PK in IS-A relationships.)\n */\n @Input() InheritedRecordPrimaryKey?: CompositeKey;\n\n /**\n * Container-driven hard hide. When true the panel is removed from view\n * regardless of search state — used by the record-form container to honor\n * `EntityFormConfig.showRelatedEntities` / `hiddenSectionKeys` /\n * `visibleSectionKeys`. Composes with (overrides) search visibility so all\n * existing `IsVisible`-based section counts stay correct.\n */\n @Input()\n set Hidden(value: boolean) {\n if (value !== this._hidden) {\n this._hidden = value;\n // Recompute visibility if content has initialized (FieldComponents present).\n if (this.FieldComponents) {\n this.UpdateVisibilityAndHighlighting();\n }\n }\n }\n get Hidden(): boolean {\n return this._hidden;\n }\n private _hidden = false;\n\n // ---- Deprecated camelCase aliases (backward compat) ----\n\n /** @deprecated Use [SectionKey] instead */\n @Input('sectionKey') set _deprecatedSectionKey(value: string) { this.SectionKey = value; }\n\n /** @deprecated Use [SectionName] instead */\n @Input('sectionName') set _deprecatedSectionName(value: string) { this.SectionName = value; }\n\n /** @deprecated Use [Icon] instead */\n @Input('icon') set _deprecatedIcon(value: string) { this.Icon = value; }\n\n /** @deprecated Use [Form] instead */\n @Input('form') set _deprecatedForm(value: unknown) { this.Form = value; }\n\n /** @deprecated Use [FormContext] instead */\n @Input('formContext') set _deprecatedFormContext(value: FormContext | undefined) { this.FormContext = value; }\n\n // ---- Outputs ----\n\n @Output() DragStarted = new EventEmitter<PanelDragStartEvent>();\n @Output() DragEnded = new EventEmitter<void>();\n @Output() PanelDrop = new EventEmitter<PanelDropEvent>();\n @Output() Navigate = new EventEmitter<FormNavigationEvent>();\n\n // ---- Content Children ----\n\n @ContentChildren(MjFormFieldComponent, { descendants: true }) FieldComponents!: QueryList<MjFormFieldComponent>;\n\n // ---- State ----\n\n DisplayName = '';\n FieldNames = '';\n IsVisible = true;\n\n @HostBinding('class')\n get HostClass(): string {\n const classes = [`mj-panel--${this.Variant}`];\n if (!this.IsVisible) classes.push('mj-search-hidden');\n if (this.IsDragging) classes.push('mj-dragging');\n if (this.IsDragOver) classes.push('mj-drag-over');\n return classes.join(' ');\n }\n\n @HostBinding('style.order')\n get CssOrder(): number {\n const formRef = this.Form as { getSectionDisplayOrder?: (key: string) => number };\n return formRef?.getSectionDisplayOrder ? formRef.getSectionDisplayOrder(this.SectionKey) : 0;\n }\n\n IsDragging = false;\n IsDragOver = false;\n\n // ---- Event relay ----\n\n /** Signals re-subscription when ContentChildren change */\n private fieldNavReset$ = new Subject<void>();\n\n // ---- Panel content resize ----\n\n @ViewChild('panelContent') private panelContentRef?: ElementRef<HTMLElement>;\n private resizeObserver?: ResizeObserver;\n private resizeDebounceTimer?: ReturnType<typeof setTimeout>;\n /** ResizeObserver fires once synchronously on observe(); that initial measurement is not a user resize. */\n private resizeObserverPrimed = false;\n\n /**\n * Persisted panel height for related-entity panels.\n * Returns undefined to let CSS default (400px) apply.\n */\n get PanelContentHeight(): number | undefined {\n if (this.Variant !== 'related-entity') return undefined;\n const formRef = this.Form as { GetSectionPanelHeight?: (key: string) => number | undefined };\n return formRef?.GetSectionPanelHeight?.(this.SectionKey);\n }\n\n /** Whether drag-to-reorder is allowed (from FormContext) */\n get ReorderAllowed(): boolean {\n return this.FormContext?.allowSectionReorder !== false;\n }\n\n /**\n * Whether this panel's header may collapse/expand. Driven by\n * `FormContext.collapsibleSections`; when false the panel renders\n * always-expanded with no toggle chevron (used by dialog/slide-in surfaces\n * that lock sections open). Undefined / true means collapsible.\n */\n get Collapsible(): boolean {\n return this.FormContext?.collapsibleSections !== false;\n }\n\n /** Whether the panel is expanded (delegates to form state; always true when not collapsible) */\n get Expanded(): boolean {\n if (!this.Collapsible) return true;\n const formRef = this.Form as { IsSectionExpanded?: (key: string, defaultExpanded?: boolean) => boolean };\n return formRef?.IsSectionExpanded ? formRef.IsSectionExpanded(this.SectionKey, this.DefaultExpanded) : true;\n }\n\n // ---- Lifecycle ----\n\n ngOnInit(): void {\n this.DisplayName = this.SectionName;\n }\n\n ngAfterContentInit(): void {\n this.UpdateFieldNames();\n this.SubscribeToFieldNavigateEvents();\n this.FieldComponents.changes.subscribe(() => {\n this.UpdateFieldNames();\n this.SubscribeToFieldNavigateEvents();\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['SectionName']) {\n this.DisplayName = this.SectionName;\n }\n if (changes['SectionName'] || changes['FormContext']) {\n this.UpdateVisibilityAndHighlighting();\n }\n if (changes['FormContext'] && this.FieldComponents) {\n this.FieldComponents.forEach(field => {\n field.FormContext = this.FormContext;\n });\n }\n }\n\n ngAfterViewInit(): void {\n this.SetupResizeObserver();\n }\n\n ngOnDestroy(): void {\n this.fieldNavReset$.next();\n this.fieldNavReset$.complete();\n this.resizeObserver?.disconnect();\n if (this.resizeDebounceTimer) {\n clearTimeout(this.resizeDebounceTimer);\n }\n }\n\n // ---- Actions ----\n\n Toggle(): void {\n if (!this.Collapsible) return;\n const formRef = this.Form as { SetSectionExpanded?: (key: string, expanded: boolean) => void };\n if (formRef?.SetSectionExpanded) {\n formRef.SetSectionExpanded(this.SectionKey, !this.Expanded);\n this.cdr.markForCheck();\n }\n }\n\n /**\n * Navigate to the parent entity when clicking the \"Inherited from X\" badge.\n * Derives the PrimaryKey from the Form's record when InheritedRecordPrimaryKey\n * is not explicitly provided (which is the common case in generated templates).\n */\n OnInheritedBadgeClick(event: MouseEvent): void {\n event.stopPropagation();\n if (!this.InheritedFromEntity) return;\n\n const primaryKey = this.InheritedRecordPrimaryKey\n ?? (this.Form as { record?: { PrimaryKey: CompositeKey } })?.record?.PrimaryKey\n ?? new CompositeKey([]);\n\n this.Navigate.emit({\n Kind: 'entity-hierarchy',\n EntityName: this.InheritedFromEntity,\n PrimaryKey: primaryKey,\n Direction: 'parent'\n });\n }\n\n // ---- Drag and Drop ----\n\n @HostListener('dragover', ['$event'])\n OnDragOver(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n event.stopPropagation();\n if (event.dataTransfer?.types.includes('text/plain')) {\n this.IsDragOver = true;\n }\n }\n\n @HostListener('dragleave', ['$event'])\n OnDragLeave(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n this.IsDragOver = false;\n }\n\n @HostListener('drop', ['$event'])\n OnDrop(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n event.preventDefault();\n event.stopPropagation();\n this.IsDragOver = false;\n\n const sourceSectionKey = event.dataTransfer?.getData('text/plain');\n if (sourceSectionKey && sourceSectionKey !== this.SectionKey) {\n this.PanelDrop.emit({\n SourceSectionKey: sourceSectionKey,\n TargetSectionKey: this.SectionKey\n });\n this.ReorderSections(sourceSectionKey, this.SectionKey);\n }\n }\n\n OnDragStart(event: DragEvent): void {\n if (!this.ReorderAllowed) return;\n this.IsDragging = true;\n event.dataTransfer?.setData('text/plain', this.SectionKey);\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n }\n this.DragStarted.emit({ SectionKey: this.SectionKey, Event: event });\n }\n\n OnDragEnd(): void {\n this.IsDragging = false;\n this.DragEnded.emit();\n }\n\n // ---- Private Methods ----\n\n private ReorderSections(sourceSectionKey: string, targetSectionKey: string): void {\n const formRef = this.Form as {\n getSectionOrder?: () => string[];\n setSectionOrder?: (order: string[]) => void;\n };\n if (!formRef?.getSectionOrder || !formRef?.setSectionOrder) return;\n\n const currentOrder = formRef.getSectionOrder();\n const sourceIndex = currentOrder.indexOf(sourceSectionKey);\n const targetIndex = currentOrder.indexOf(targetSectionKey);\n if (sourceIndex === -1 || targetIndex === -1) return;\n\n const newOrder = [...currentOrder];\n newOrder.splice(sourceIndex, 1);\n newOrder.splice(targetIndex, 0, sourceSectionKey);\n formRef.setSectionOrder(newOrder);\n this.cdr.markForCheck();\n }\n\n private UpdateFieldNames(): void {\n if (this.FieldComponents) {\n const names: string[] = [];\n this.FieldComponents.forEach(field => {\n if (field.DisplayName) {\n names.push(field.DisplayName.toLowerCase());\n }\n });\n this.FieldNames = names.join(' ');\n this.UpdateVisibilityAndHighlighting();\n }\n }\n\n /**\n * Subscribes to Navigate events from all child form-field components\n * and relays them through this panel's Navigate output.\n */\n private SubscribeToFieldNavigateEvents(): void {\n this.fieldNavReset$.next(); // tear down previous subscriptions\n this.FieldComponents.forEach(field => {\n field.Navigate.pipe(takeUntil(this.fieldNavReset$)).subscribe((event: FormNavigationEvent) => {\n this.Navigate.emit(event);\n });\n });\n }\n\n /**\n * Sets up a ResizeObserver on the panel content div for related-entity panels.\n * When the user drags the CSS resize handle, we persist the new height.\n */\n private SetupResizeObserver(): void {\n if (this.Variant !== 'related-entity' || !this.panelContentRef) return;\n\n const el = this.panelContentRef.nativeElement;\n // Run outside Angular zone to avoid triggering change detection on every resize frame\n this.ngZone.runOutsideAngular(() => {\n this.resizeObserver = new ResizeObserver((entries) => {\n // Skip the synchronous initial fire emitted when observe() is called — it's the\n // panel's own first measurement on load, not a user-initiated resize. Persisting\n // it would write a spurious panelHeight for every panel on form open.\n if (!this.resizeObserverPrimed) {\n this.resizeObserverPrimed = true;\n return;\n }\n // Only a height change while the panel is expanded reflects a genuine user drag of\n // the resize handle. Ignore reflows while collapsed (e.g. content settling on load).\n if (!this.Expanded) return;\n const entry = entries[0];\n if (!entry) return;\n const newHeight = Math.round(entry.contentRect.height);\n this.DebouncePersistHeight(newHeight);\n });\n this.resizeObserver.observe(el);\n });\n }\n\n /**\n * Debounces height persistence so we don't write to DB on every resize frame.\n */\n private DebouncePersistHeight(height: number): void {\n if (this.resizeDebounceTimer) {\n clearTimeout(this.resizeDebounceTimer);\n }\n this.resizeDebounceTimer = setTimeout(() => {\n const formRef = this.Form as { SetSectionPanelHeight?: (key: string, height: number) => void };\n formRef?.SetSectionPanelHeight?.(this.SectionKey, height);\n }, 500);\n }\n\n private UpdateVisibilityAndHighlighting(): void {\n // Hard hide takes precedence over search state. Driven by an explicit\n // `Hidden` input OR the form config's section-visibility rules carried on\n // FormContext (which also reach slot-injected BaseFormPanels, since every\n // panel receives FormContext).\n if (this._hidden || IsFormSectionHidden(this.FormContext, this.SectionKey, this.Variant)) {\n this.IsVisible = false;\n this.DisplayName = EscapeHTML(this.SectionName);\n this.cdr.markForCheck();\n return;\n }\n\n const searchTerm = (this.FormContext?.sectionFilter || '').toLowerCase().trim();\n\n if (!searchTerm) {\n this.IsVisible = true;\n this.DisplayName = this.SectionName;\n this.cdr.markForCheck();\n return;\n }\n\n const sectionMatches = this.SectionName.toLowerCase().includes(searchTerm);\n const fieldsMatch = this.FieldNames.includes(searchTerm);\n this.IsVisible = sectionMatches || fieldsMatch;\n\n // DisplayName is bound to `[innerHTML]` in the template — must always be HTML-safe.\n this.DisplayName =\n this.IsVisible && sectionMatches\n ? HighlightSearchMatches(this.SectionName, searchTerm, 'mj-forms-search-highlight')\n : EscapeHTML(this.SectionName);\n\n this.cdr.markForCheck();\n }\n}\n","<div class=\"mj-forms-panel\"\n [class.mj-forms-panel--related]=\"Variant === 'related-entity'\"\n [class.mj-forms-panel--inherited]=\"Variant === 'inherited'\"\n [attr.data-section-key]=\"SectionKey\">\n\n <!-- Panel Header -->\n <div class=\"mj-forms-panel-header\"\n [class.mj-forms-panel-header--static]=\"!Collapsible\"\n [attr.role]=\"Collapsible ? 'button' : null\"\n [attr.tabindex]=\"Collapsible ? 0 : null\"\n (click)=\"Toggle()\">\n <!-- Drag Handle (hidden when reorder disabled) -->\n @if (ReorderAllowed) {\n <div class=\"mj-forms-drag-handle\"\n title=\"Drag to reorder sections\"\n draggable=\"true\"\n (dragstart)=\"OnDragStart($event)\"\n (dragend)=\"OnDragEnd()\"\n (click)=\"$event.stopPropagation()\">\n <i class=\"fa-solid fa-grip-vertical\"></i>\n </div>\n }\n\n <!-- Icon + Title -->\n <div class=\"mj-forms-panel-title-group\">\n <i [class]=\"Icon\" class=\"mj-forms-panel-icon\"></i>\n <h3 class=\"mj-forms-panel-title\">\n <span [innerHTML]=\"DisplayName\"></span>\n <!-- Row count badge for related entities -->\n @if (BadgeCount !== undefined) {\n <span class=\"mj-forms-row-count-badge\" [class.mj-forms-row-count-badge--zero]=\"BadgeCount === 0\">\n {{ BadgeCount }}\n </span>\n }\n </h3>\n </div>\n\n <!-- Inherited From badge (IS-A) -->\n @if (Variant === 'inherited' && InheritedFromEntity) {\n <a class=\"mj-forms-inherited-badge\" (click)=\"OnInheritedBadgeClick($event)\"\n [title]=\"'View parent record: ' + InheritedFromEntity\">\n <i class=\"fa-solid fa-arrow-up\"></i>\n Inherited from {{ InheritedFromEntity }}\n </a>\n }\n\n <!-- Chevron (hidden when sections are locked open) -->\n @if (Collapsible) {\n <div class=\"mj-forms-panel-chevron\">\n <i [class]=\"Expanded ? 'fa fa-chevron-up' : 'fa fa-chevron-down'\"></i>\n </div>\n }\n </div>\n\n <!-- Panel Body -->\n <div class=\"mj-forms-panel-body\" [class.mj-forms-panel-body--collapsed]=\"!Expanded\">\n <div class=\"mj-forms-panel-content\"\n #panelContent\n [style.height.px]=\"PanelContentHeight\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n"]}
@@ -0,0 +1,97 @@
1
+ import { BaseEntity, ValidationResult } from '@memberjunction/core';
2
+ import { BaseFormComponent } from '../base-form-component';
3
+ import { FormContext } from '../types/form-types';
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Well-known slot positions where panels can be injected into a generated
7
+ * entity form. Used as the `slot` field in a panel's registration metadata.
8
+ *
9
+ * Slot positions inside the form, top to bottom:
10
+ *
11
+ * ┌─ <mj-record-form-container>
12
+ * │ [top-area slot] ← CodeGen-emitted; rare (entities with top-area section)
13
+ * │ [before-fields slot] ← CodeGen-emitted; banners / warnings above field panels
14
+ * │ <connection details>
15
+ * │ <other generated field panels>
16
+ * │ [after-fields slot] ← CodeGen-emitted; typed config knobs, secondary settings — most common slot
17
+ * │ <content items grid>
18
+ * │ <other related-entity grids>
19
+ * │ [after-related slot] ← CodeGen-emitted; bottom-of-form addenda
20
+ * │ [after-everything slot] ← Container-emitted; ALWAYS present (fallback target)
21
+ * └─ </mj-record-form-container>
22
+ *
23
+ * Pick the slot that matches the panel's role. `after-fields` is the default
24
+ * for most "additional settings" panels — it sits in the field column, before
25
+ * the related-entity grids.
26
+ *
27
+ * **Fallback behavior** — see `FormSlotCoordinator`. If the registered slot is
28
+ * missing in the current form (CodeGen hasn't been rerun against the new
29
+ * template emitter), the panel walks forward in the chain until it finds an
30
+ * existing slot. `after-everything` is always emitted by the container, so
31
+ * fallback never dead-ends. Pre-CodeGen-regen forms show every panel at the
32
+ * bottom of the form; post-regen forms show them in the preferred position.
33
+ */
34
+ export type FormPanelSlot = 'top-area' | 'before-fields' | 'after-fields' | 'after-related' | 'after-everything';
35
+ /**
36
+ * Shape of the `metadata` object every BaseFormPanel registration MUST attach
37
+ * via `@RegisterClass(BaseFormPanel, { metadata: {...} })`. The
38
+ * `<mj-form-panel-slot>` host filters registrations by matching against this
39
+ * shape — registrations without it are silently ignored.
40
+ *
41
+ * - `entity` — the `MJContentSourceEntity_IContentSourceConfiguration`-style
42
+ * entity name. Must match the entity-form's record entity exactly
43
+ * (case-sensitive trim-equality enforced by the slot host).
44
+ * - `slot` — which slot the panel renders into.
45
+ * - `sortKey`— higher = earlier within the slot. Defaults to 0 if omitted.
46
+ * Use ranges (e.g., 100/50/10) so future panels can wedge in
47
+ * without recomputing every neighbor's sort.
48
+ */
49
+ export interface FormPanelRegistrationMetadata extends Record<string, unknown> {
50
+ entity: string;
51
+ slot: FormPanelSlot;
52
+ sortKey?: number;
53
+ }
54
+ /**
55
+ * Abstract base for every dynamically-injectable form panel.
56
+ *
57
+ * Subclasses are standalone Angular components decorated with
58
+ * `@RegisterClass(BaseFormPanel, { metadata: { entity, slot, sortKey? } })`.
59
+ * At runtime, `<mj-form-panel-slot>` discovers matching registrations via
60
+ * `ClassFactory.GetAllRegistrationsByMetadata`, instantiates each via
61
+ * `ViewContainerRef.createComponent`, and wires `Record` + `FormComponent` +
62
+ * `FormContext` into the inputs.
63
+ *
64
+ * Lifecycle hooks: standard Angular `ngOnInit` / `ngOnDestroy` work as usual.
65
+ * `Record` is guaranteed to be set before the first change-detection pass.
66
+ *
67
+ * Optional `validate()` returns a synchronous validation result; the parent
68
+ * `BaseFormComponent.Save()` path will surface it via the existing validation
69
+ * pipeline when called. Panels that don't validate anything beyond what the
70
+ * record itself does can leave this method off.
71
+ */
72
+ export declare abstract class BaseFormPanel<TRecord extends BaseEntity = BaseEntity> {
73
+ /** The entity record being edited. Set by the slot host before view init. */
74
+ Record: TRecord;
75
+ /** The host form component (use for EditMode, dirty notifications, etc). Set by the slot host. */
76
+ FormComponent: BaseFormComponent;
77
+ /** Optional form context — same shape the collapsible-panel chrome expects. Set by the slot host. */
78
+ FormContext?: FormContext;
79
+ /**
80
+ * Convenience getter for read-only / edit-mode rendering. Falls back to
81
+ * `false` when the panel is shown outside a `BaseFormComponent` host (e.g.,
82
+ * a dashboard quick-edit dialog reusing the same panel — see the
83
+ * "composable panel" docs).
84
+ */
85
+ get EditMode(): boolean;
86
+ /**
87
+ * Override to add per-panel validation that should block the parent form's
88
+ * Save(). Return `{ Success: true, Errors: [] }` when valid, or include
89
+ * `ValidationErrorInfo` entries to surface field-level errors. The default
90
+ * implementation reports valid (panels that don't need extra validation
91
+ * can leave this method off).
92
+ */
93
+ validate(): ValidationResult;
94
+ static ɵfac: i0.ɵɵFactoryDeclaration<BaseFormPanel<any>, never>;
95
+ static ɵdir: i0.ɵɵDirectiveDeclaration<BaseFormPanel<any>, never, never, { "Record": { "alias": "Record"; "required": false; }; "FormComponent": { "alias": "FormComponent"; "required": false; }; "FormContext": { "alias": "FormContext"; "required": false; }; }, {}, never, never, true, never>;
96
+ }
97
+ //# sourceMappingURL=base-form-panel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-form-panel.d.ts","sourceRoot":"","sources":["../../../src/lib/panel-slot/base-form-panel.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,aAAa,GACnB,UAAU,GACV,eAAe,GACf,cAAc,GACd,eAAe,GACf,kBAAkB,CAAC;AAEzB;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,6BAA8B,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,8BACsB,aAAa,CAAC,OAAO,SAAS,UAAU,GAAG,UAAU;IACvE,6EAA6E;IACpE,MAAM,EAAG,OAAO,CAAC;IAC1B,kGAAkG;IACzF,aAAa,EAAG,iBAAiB,CAAC;IAC3C,qGAAqG;IAC5F,WAAW,CAAC,EAAE,WAAW,CAAC;IAEnC;;;;;OAKG;IACH,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED;;;;;;OAMG;IACI,QAAQ,IAAI,gBAAgB;yCAzBjB,aAAa;2CAAb,aAAa;CAgClC"}