@ruc-lib/overlay 2.0.10 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,27 +17,38 @@ If you only need the Overlay component:
17
17
  npm install @ruc-lib/overlay
18
18
  ```
19
19
 
20
- ## Usage
20
+ ## Version Compatibility
21
+
22
+ Please ensure you install the correct version of `@ruc-lib/overlay` based on your Angular version.
23
+
24
+ | Angular Version | Compatible `@ruc-lib/overlay` Version |
25
+ |--------------------|---------------------------------------------|
26
+ | 15.x.x | `npm install @ruc-lib/overlay@^3.0.0` |
27
+ | 16.x.x | `npm install @ruc-lib/overlay@^3.0.0` |
21
28
 
22
- ### 1. Import the Module
23
- In your Angular module file (e.g., `app.module.ts`), import the `RuclibOverlayModule`:
24
29
 
25
- ```typescript
26
- import { RuclibOverlayModule } from '@ruc-lib/overlay';
27
- import { AppComponent } from './app.component';
28
- import { NgModule } from '@angular/core';
29
- import { BrowserModule } from '@angular/platform-browser';
30
-
31
- @NgModule({
32
- declarations: [AppComponent],
33
- imports: [
34
- BrowserModule,
35
- RuclibOverlayModule
36
- ],
37
- providers: [],
38
- bootstrap: [AppComponent]
39
- })
40
- export class AppModule {}
30
+ ## Usage
31
+
32
+ ### 1. Import the Component
33
+ In your Angular component file (e.g., `app.component.ts`), import the `RuclibOverlayComponent`:
34
+
35
+ ```typescript
36
+ import { Component } from '@angular/core';
37
+
38
+ // For Complete Library
39
+ import { RuclibOverlayComponent } from '@uxpractice/ruc-lib/overlay';
40
+
41
+ // For Individual Package
42
+ import { RuclibOverlayComponent } from '@ruc-lib/overlay';
43
+
44
+ @Component({
45
+ selector: 'app-root',
46
+ imports: [RuclibOverlayComponent],
47
+ templateUrl: './app.component.html',
48
+ })
49
+ export class AppComponent {
50
+ // Component code here
51
+ }
41
52
  ```
42
53
  ### 2. Update the style.scss file
43
54
  @use 'sass:map';
@@ -257,10 +268,26 @@ export class AppComponent implements AfterViewInit {
257
268
  </button>
258
269
  <!---->
259
270
 
271
+ > ⚠️ **IMPORTANT: Custom Theme Usage in Angular Material**
272
+
273
+ When implementing **custom themes**, such as:
274
+
275
+ ```scss
276
+ .custom-theme-1 {
277
+ @include angular-material-theme($custom-theme);
278
+ }
279
+
280
+ // You must also include the typography mixin to ensure text styles are applied correctly as shown below:
281
+ .custom-theme-1 {
282
+ @include angular-material-theme($custom-theme);
283
+ @include mat.typography-level($theme-custom-typography-name, body-1);
284
+ }
285
+ ```
286
+
260
287
  ## Contribution
261
288
 
262
289
  Contributions are welcome! Feel free to open issues or pull requests for any enhancements or fixes.
263
290
 
264
291
  ## Acknowledgements
265
292
 
266
- Thank you for choosing the Overlay component. If you have any feedback or suggestions, please let us know!
293
+ Thank you for choosing the Overlay component. If you have any feedback or suggestions, please let us know!
@@ -0,0 +1,355 @@
1
+ import * as i1$1 from '@angular/cdk/overlay';
2
+ import * as i0 from '@angular/core';
3
+ import { InjectionToken, Injectable, Input, ChangeDetectionStrategy, Component, EventEmitter, TemplateRef, HostBinding, Output, Inject, Injector, ElementRef, HostListener, ViewChild } from '@angular/core';
4
+ import { Subject, filter } from 'rxjs';
5
+ import { ComponentPortal } from '@angular/cdk/portal';
6
+ import * as i3 from '@angular/material/icon';
7
+ import { MatIconModule } from '@angular/material/icon';
8
+ import { trigger, state, transition, style, animate } from '@angular/animations';
9
+ import * as i1 from '@angular/common';
10
+ import { CommonModule } from '@angular/common';
11
+ import Chart from 'chart.js/auto';
12
+ import * as i2 from '@angular/material/card';
13
+ import { MatCardModule } from '@angular/material/card';
14
+ import * as i4 from '@angular/material/button';
15
+ import { MatButtonModule, MatButton } from '@angular/material/button';
16
+ import { ESCAPE } from '@angular/cdk/keycodes';
17
+
18
+ /**
19
+ * The Injection Token used to provide the PopoverControl object to the
20
+ * PopoverContentComponent. This is the correct, final version.
21
+ */
22
+ const OVERLAY_CONTROL = new InjectionToken('OVERLAY_CONTROL');
23
+
24
+ class OverlayService {
25
+ constructor() {
26
+ this.popoverState = new Subject();
27
+ this.popoverState$ = this.popoverState.asObservable();
28
+ }
29
+ /**
30
+ * Broadcasts a command to open a popover using the OverlayData structure.
31
+ */
32
+ open(config, trigger) {
33
+ console.log(config, trigger);
34
+ // The service's responsibility is to bundle the config and trigger
35
+ // into a PopoverData object and send it.
36
+ this.popoverState.next({ config, trigger });
37
+ }
38
+ /**
39
+ * Broadcasts a command to close any currently open service-controlled popover.
40
+ */
41
+ close() {
42
+ this.popoverState.next(null);
43
+ }
44
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OverlayService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
45
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OverlayService, providedIn: 'root' }); }
46
+ }
47
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OverlayService, decorators: [{
48
+ type: Injectable,
49
+ args: [{
50
+ providedIn: 'root'
51
+ }]
52
+ }] });
53
+
54
+ class RucOverlayChartComponent {
55
+ constructor() {
56
+ this.index = 0;
57
+ }
58
+ ngAfterViewInit() {
59
+ if (this.chartConfig) {
60
+ this.chart = new Chart('canvas' + this.index, this.chartConfig);
61
+ }
62
+ }
63
+ ngOnDestroy() {
64
+ this.chart?.destroy();
65
+ this.chart = null;
66
+ this.chartConfig = null;
67
+ }
68
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RucOverlayChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
69
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.9", type: RucOverlayChartComponent, isStandalone: true, selector: "uxp-ruc-overlay-chart", inputs: { index: "index", chartConfig: "chartConfig" }, ngImport: i0, template: "<div style=\"position: relative; height:220px;\">\r\n <canvas id=\"canvas{{index}}\">{{chart}}</canvas>\r\n</div>\r\n", styles: [""], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
70
+ }
71
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RucOverlayChartComponent, decorators: [{
72
+ type: Component,
73
+ args: [{ selector: 'uxp-ruc-overlay-chart', imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div style=\"position: relative; height:220px;\">\r\n <canvas id=\"canvas{{index}}\">{{chart}}</canvas>\r\n</div>\r\n" }]
74
+ }], propDecorators: { index: [{
75
+ type: Input
76
+ }], chartConfig: [{
77
+ type: Input
78
+ }] } });
79
+
80
+ class OverlayContentComponent {
81
+ ngOnInit() {
82
+ if (this.control.config.tableData) {
83
+ this.getTableHeaders();
84
+ }
85
+ }
86
+ get animationState() {
87
+ return this.control.config.animation === 'scale'
88
+ ? 'enter-scale'
89
+ : 'enter-fade';
90
+ }
91
+ constructor(control) {
92
+ this.control = control;
93
+ this.actualPlacement = 'bottom';
94
+ this.tableHeaders = [];
95
+ this.arrowOffset = 0;
96
+ this.mouseEnterPopover = new EventEmitter();
97
+ this.mouseLeavePopover = new EventEmitter();
98
+ this.actualPlacement = this.control.config.placement || 'bottom';
99
+ }
100
+ // Helper to check if content is a TemplateRef
101
+ isTemplateRef(content) {
102
+ return content instanceof TemplateRef;
103
+ }
104
+ // Helper to get keys for the table header, robustly
105
+ getTableHeaders() {
106
+ const tempData = this.control.config.tableData;
107
+ if (!tempData || tempData.length === 0) {
108
+ this.tableHeaders = [];
109
+ return;
110
+ }
111
+ // Assumes all objects in the array have the same shape
112
+ this.tableHeaders = Object.keys(tempData[0]);
113
+ }
114
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OverlayContentComponent, deps: [{ token: OVERLAY_CONTROL }], target: i0.ɵɵFactoryTarget.Component }); }
115
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: OverlayContentComponent, isStandalone: true, selector: "uxp-overlay-content", inputs: { customTheme: "customTheme" }, outputs: { mouseEnterPopover: "mouseEnterPopover", mouseLeavePopover: "mouseLeavePopover" }, host: { properties: { "@popoverAnimation": "this.animationState" } }, ngImport: i0, template: "<mat-card class=\"popover-container\" class={{customTheme}} (click)=\"$event.stopPropagation()\">\r\n\r\n <div class=\"popover-arrow\"\r\n [attr.data-placement]=\"actualPlacement\"\r\n [style.left.px]=\"(actualPlacement.startsWith('top') || actualPlacement.startsWith('bottom')) ? arrowOffset : null\"\r\n [style.top.px]=\"(actualPlacement.startsWith('left') || actualPlacement.startsWith('right')) ? arrowOffset : null\">\r\n </div>\r\n <!-- Header with optional title and close button -->\r\n\r\n @if (\r\n control.config.overlayTitle ||\r\n control.config.showCloseButton ||\r\n control.config.closeIcon\r\n ) {\r\n <mat-card-header\r\n class=\"popover-header\"\r\n >\r\n @if (control.config.overlayTitle) {\r\n <mat-card-title class=\"popover-title\">{{ control.config.overlayTitle }}</mat-card-title>\r\n }\r\n @if (control.config.showCloseButton && control.config.closeIcon) {\r\n <button mat-icon-button class=\"close-btn\" (click)=\"control.close()\" color=\"primary\" aria-label=\"Close popover icon\">\r\n <mat-icon>{{ control.config.closeIcon }}</mat-icon>\r\n </button>\r\n }\r\n </mat-card-header>\r\n }\r\n\r\n\r\n <!-- Body with dynamic content -->\r\n <mat-card-content class=\"popover-body\">\r\n <!-- Case 1: Content is a simple string -->\r\n @if (\r\n !isTemplateRef(control.config.content) && !control.config.tableData\r\n ) {\r\n {{ control.config.content }}\r\n }\r\n\r\n <!-- Case 2: Content is a TemplateRef -->\r\n @if (isTemplateRef(control.config.content)) {\r\n <ng-container *ngTemplateOutlet=\"control.config.content\"></ng-container>\r\n }\r\n\r\n @if (control.config.chartConfig) {\r\n <uxp-ruc-overlay-chart [chartConfig]=\"control.config.chartConfig\"></uxp-ruc-overlay-chart>\r\n }\r\n\r\n <!-- Case 3: Content is table data -->\r\n @if (control.config.tableData?.length) {\r\n <table\r\n class=\"popover-table\"\r\n [class]=\"control.config.tableClass || 'basic-table'\"\r\n >\r\n <thead>\r\n <tr>\r\n @for (header of this.tableHeaders!; track header) {\r\n <th\r\n >\r\n {{ header }}\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of control.config.tableData; track row) {\r\n <tr>\r\n @for (header of this.tableHeaders!; track header) {\r\n <td\r\n >\r\n {{ row[header] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n </mat-card-content>\r\n</mat-card>\r\n", styles: [":host{display:block}.popover-container{z-index:1080;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px #0003;position:relative;max-width:300px}.popover-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid;border-width:10px}.close-btn .mat-mdc-icon-button.mat-mdc-button-base{width:30px;height:30px;padding:2px}.popover-title{font-size:16px;font-weight:600}.mat-card-header.mat-mdc-card-header.popover-header .mat-mdc-card-header-text .mat-card-title.mat-mdc-card-title{font-size:16px}button.close-btn.mdc-icon-button.mat-mdc-icon-button.mat-mdc-button-base{width:30px;height:30px;padding:2px}.popover-arrow[data-placement^=bottom]{top:-10px;transform:translate(-50%);border-width:0 10px 10px 10px;border-bottom-color:#fff;filter:drop-shadow(0 -1px 1px rgba(0,0,0,.15))}.popover-arrow[data-placement^=top]{bottom:-10px;transform:translate(-50%);border-width:10px 10px 0 10px;border-top-color:#fff;filter:drop-shadow(0 1px 1px rgba(0,0,0,.15))}.popover-arrow[data-placement^=right]{left:-10px;transform:translateY(-50%);border-width:10px 10px 10px 0;border-right-color:#fff;filter:drop-shadow(-1px 0 1px rgba(0,0,0,.15))}.popover-arrow[data-placement^=left]{right:-10px;transform:translateY(-50%);border-width:10px 0 10px 10px;border-left-color:#fff;filter:drop-shadow(1px 0 1px rgba(0,0,0,.15))}.popover-header{display:flex;justify-content:space-between;align-items:center;padding:.5rem 1rem;margin:0;font-size:1rem;border-bottom:1px solid #dcdcdc;border-radius:5px 5px 0 0}.popover-header h3{margin:0;font-size:1rem}.popover-body{padding:9px 14px}.popover-table{width:100%;border-collapse:collapse;margin-top:5px}.popover-table th,.popover-table td{border:1px solid #ddd;padding:8px;text-align:left}.popover-table th{text-transform:capitalize}.striped-table{width:100%;border-collapse:collapse;font-size:.9em}.striped-table th,.striped-table td{border:1px solid #ddd;padding:8px;text-align:left}.striped-table thead th{font-weight:700}.striped-table tbody tr:nth-child(2n){background-color:#00000061}.basic-table{width:100%;border-collapse:collapse;font-size:.9em}.basic-table th,.basic-table td{border:1px solid #ddd;padding:8px;text-align:left}.basic-table thead th{font-weight:700}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: RucOverlayChartComponent, selector: "uxp-ruc-overlay-chart", inputs: ["index", "chartConfig"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i2.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i2.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }], animations: [
116
+ trigger('popoverAnimation', [
117
+ state('void', style({ transform: 'scale(0.9)', opacity: 0 })),
118
+ state('enter-scale', style({ transform: 'scale(1)', opacity: 1 })),
119
+ state('enter-fade', style({ opacity: 1 })),
120
+ transition('void => enter-scale', animate('150ms cubic-bezier(0, 0, 0.2, 1)')),
121
+ transition('void => enter-fade', [
122
+ style({ opacity: 0, transform: 'translateY(10px)' }),
123
+ animate('500ms', style({ opacity: 1, transform: 'translateY(0)' })),
124
+ ]),
125
+ transition('* => void', [
126
+ animate('500ms', style({ opacity: 0, transform: 'translateY(10px)' })),
127
+ ]),
128
+ ]),
129
+ ] }); }
130
+ }
131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: OverlayContentComponent, decorators: [{
132
+ type: Component,
133
+ args: [{ selector: 'uxp-overlay-content', imports: [CommonModule, RucOverlayChartComponent, MatCardModule, MatIconModule, MatButtonModule], animations: [
134
+ trigger('popoverAnimation', [
135
+ state('void', style({ transform: 'scale(0.9)', opacity: 0 })),
136
+ state('enter-scale', style({ transform: 'scale(1)', opacity: 1 })),
137
+ state('enter-fade', style({ opacity: 1 })),
138
+ transition('void => enter-scale', animate('150ms cubic-bezier(0, 0, 0.2, 1)')),
139
+ transition('void => enter-fade', [
140
+ style({ opacity: 0, transform: 'translateY(10px)' }),
141
+ animate('500ms', style({ opacity: 1, transform: 'translateY(0)' })),
142
+ ]),
143
+ transition('* => void', [
144
+ animate('500ms', style({ opacity: 0, transform: 'translateY(10px)' })),
145
+ ]),
146
+ ]),
147
+ ], template: "<mat-card class=\"popover-container\" class={{customTheme}} (click)=\"$event.stopPropagation()\">\r\n\r\n <div class=\"popover-arrow\"\r\n [attr.data-placement]=\"actualPlacement\"\r\n [style.left.px]=\"(actualPlacement.startsWith('top') || actualPlacement.startsWith('bottom')) ? arrowOffset : null\"\r\n [style.top.px]=\"(actualPlacement.startsWith('left') || actualPlacement.startsWith('right')) ? arrowOffset : null\">\r\n </div>\r\n <!-- Header with optional title and close button -->\r\n\r\n @if (\r\n control.config.overlayTitle ||\r\n control.config.showCloseButton ||\r\n control.config.closeIcon\r\n ) {\r\n <mat-card-header\r\n class=\"popover-header\"\r\n >\r\n @if (control.config.overlayTitle) {\r\n <mat-card-title class=\"popover-title\">{{ control.config.overlayTitle }}</mat-card-title>\r\n }\r\n @if (control.config.showCloseButton && control.config.closeIcon) {\r\n <button mat-icon-button class=\"close-btn\" (click)=\"control.close()\" color=\"primary\" aria-label=\"Close popover icon\">\r\n <mat-icon>{{ control.config.closeIcon }}</mat-icon>\r\n </button>\r\n }\r\n </mat-card-header>\r\n }\r\n\r\n\r\n <!-- Body with dynamic content -->\r\n <mat-card-content class=\"popover-body\">\r\n <!-- Case 1: Content is a simple string -->\r\n @if (\r\n !isTemplateRef(control.config.content) && !control.config.tableData\r\n ) {\r\n {{ control.config.content }}\r\n }\r\n\r\n <!-- Case 2: Content is a TemplateRef -->\r\n @if (isTemplateRef(control.config.content)) {\r\n <ng-container *ngTemplateOutlet=\"control.config.content\"></ng-container>\r\n }\r\n\r\n @if (control.config.chartConfig) {\r\n <uxp-ruc-overlay-chart [chartConfig]=\"control.config.chartConfig\"></uxp-ruc-overlay-chart>\r\n }\r\n\r\n <!-- Case 3: Content is table data -->\r\n @if (control.config.tableData?.length) {\r\n <table\r\n class=\"popover-table\"\r\n [class]=\"control.config.tableClass || 'basic-table'\"\r\n >\r\n <thead>\r\n <tr>\r\n @for (header of this.tableHeaders!; track header) {\r\n <th\r\n >\r\n {{ header }}\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of control.config.tableData; track row) {\r\n <tr>\r\n @for (header of this.tableHeaders!; track header) {\r\n <td\r\n >\r\n {{ row[header] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n </mat-card-content>\r\n</mat-card>\r\n", styles: [":host{display:block}.popover-container{z-index:1080;border:1px solid rgba(0,0,0,.2);border-radius:6px;box-shadow:0 5px 10px #0003;position:relative;max-width:300px}.popover-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid;border-width:10px}.close-btn .mat-mdc-icon-button.mat-mdc-button-base{width:30px;height:30px;padding:2px}.popover-title{font-size:16px;font-weight:600}.mat-card-header.mat-mdc-card-header.popover-header .mat-mdc-card-header-text .mat-card-title.mat-mdc-card-title{font-size:16px}button.close-btn.mdc-icon-button.mat-mdc-icon-button.mat-mdc-button-base{width:30px;height:30px;padding:2px}.popover-arrow[data-placement^=bottom]{top:-10px;transform:translate(-50%);border-width:0 10px 10px 10px;border-bottom-color:#fff;filter:drop-shadow(0 -1px 1px rgba(0,0,0,.15))}.popover-arrow[data-placement^=top]{bottom:-10px;transform:translate(-50%);border-width:10px 10px 0 10px;border-top-color:#fff;filter:drop-shadow(0 1px 1px rgba(0,0,0,.15))}.popover-arrow[data-placement^=right]{left:-10px;transform:translateY(-50%);border-width:10px 10px 10px 0;border-right-color:#fff;filter:drop-shadow(-1px 0 1px rgba(0,0,0,.15))}.popover-arrow[data-placement^=left]{right:-10px;transform:translateY(-50%);border-width:10px 0 10px 10px;border-left-color:#fff;filter:drop-shadow(1px 0 1px rgba(0,0,0,.15))}.popover-header{display:flex;justify-content:space-between;align-items:center;padding:.5rem 1rem;margin:0;font-size:1rem;border-bottom:1px solid #dcdcdc;border-radius:5px 5px 0 0}.popover-header h3{margin:0;font-size:1rem}.popover-body{padding:9px 14px}.popover-table{width:100%;border-collapse:collapse;margin-top:5px}.popover-table th,.popover-table td{border:1px solid #ddd;padding:8px;text-align:left}.popover-table th{text-transform:capitalize}.striped-table{width:100%;border-collapse:collapse;font-size:.9em}.striped-table th,.striped-table td{border:1px solid #ddd;padding:8px;text-align:left}.striped-table thead th{font-weight:700}.striped-table tbody tr:nth-child(2n){background-color:#00000061}.basic-table{width:100%;border-collapse:collapse;font-size:.9em}.basic-table th,.basic-table td{border:1px solid #ddd;padding:8px;text-align:left}.basic-table thead th{font-weight:700}\n"] }]
148
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
149
+ type: Inject,
150
+ args: [OVERLAY_CONTROL]
151
+ }] }], propDecorators: { customTheme: [{
152
+ type: Input
153
+ }], mouseEnterPopover: [{
154
+ type: Output
155
+ }], mouseLeavePopover: [{
156
+ type: Output
157
+ }], animationState: [{
158
+ type: HostBinding,
159
+ args: ['@popoverAnimation']
160
+ }] } });
161
+
162
+ const positions = [
163
+ { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 10 },
164
+ { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -10 },
165
+ { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 10 },
166
+ { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -10 }
167
+ ];
168
+
169
+ class RuclibOverlayComponent {
170
+ constructor(overlay, injector, overlayService) {
171
+ this.overlay = overlay;
172
+ this.injector = injector;
173
+ this.overlayService = overlayService;
174
+ this.rucInputData = {
175
+ content: 'Default content',
176
+ };
177
+ this.overlayRef = null;
178
+ }
179
+ ngOnInit() {
180
+ if (!this.buttonText) {
181
+ this.serviceSubscription = this.overlayService.popoverState$.subscribe((data) => {
182
+ if (data && !this.isOpen) {
183
+ this.show(data.trigger, data.config);
184
+ }
185
+ else if (!data) {
186
+ this.destroy();
187
+ }
188
+ });
189
+ }
190
+ }
191
+ ngOnDestroy() {
192
+ this.positionSubscription?.unsubscribe();
193
+ this.serviceSubscription?.unsubscribe();
194
+ this.destroy();
195
+ }
196
+ get isOpen() {
197
+ return !!this.overlayRef;
198
+ }
199
+ // --- Trigger Handlers for self-contained button ---
200
+ toggle() {
201
+ if (this.rucInputData.trigger !== 'hover') {
202
+ this.isOpen
203
+ ? this.destroy()
204
+ : this.show(this.triggerButtonRef.nativeElement, this.rucInputData);
205
+ }
206
+ }
207
+ handleMouseEnter() {
208
+ if (this.rucInputData.trigger === 'hover') {
209
+ if (this.closeTimeout)
210
+ clearTimeout(this.closeTimeout); // Clear any pending close command
211
+ this.show(this.triggerButtonRef.nativeElement, this.rucInputData);
212
+ }
213
+ }
214
+ handleMouseLeave() {
215
+ if (this.rucInputData.trigger === 'hover') {
216
+ // Use the configurable closeDelay
217
+ const delay = this.rucInputData.closeDelay ?? 200;
218
+ this.closeTimeout = setTimeout(() => this.destroy(), delay);
219
+ }
220
+ }
221
+ show(trigger, config) {
222
+ if (this.isOpen)
223
+ return;
224
+ const positionStrategy = this.createPositionStrategy(trigger, config.placement || 'bottom');
225
+ this.overlayRef = this.overlay.create({
226
+ positionStrategy,
227
+ hasBackdrop: config.trigger !== 'hover',
228
+ backdropClass: 'cdk-overlay-transparent-backdrop',
229
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
230
+ });
231
+ this.overlayRef.keydownEvents().pipe(filter(event => event.keyCode === ESCAPE)).subscribe(() => this.destroy());
232
+ const control = { config, close: this.destroy.bind(this) };
233
+ const injector = Injector.create({
234
+ parent: this.injector,
235
+ providers: [{ provide: OVERLAY_CONTROL, useValue: control }],
236
+ });
237
+ const portal = new ComponentPortal(OverlayContentComponent, null, injector);
238
+ const componentRef = this.overlayRef.attach(portal);
239
+ componentRef.instance.customTheme = this.customTheme;
240
+ // --- START: MODIFICATION FOR DYNAMIC ARROW ---
241
+ this.positionSubscription = positionStrategy.positionChanges.subscribe((change) => {
242
+ // 1. Get the new placement ('top', 'bottom', etc.)
243
+ const newPlacement = this.getPlacementFromPosition(change.connectionPair);
244
+ componentRef.instance.actualPlacement = newPlacement;
245
+ // 2. Calculate the arrow's offset
246
+ if (this.overlayRef) {
247
+ const triggerRect = trigger.getBoundingClientRect();
248
+ const popoverRect = this.overlayRef.overlayElement.getBoundingClientRect();
249
+ let arrowOffset = 0;
250
+ // If popover is top/bottom, arrow moves horizontally (left)
251
+ if (newPlacement.startsWith('top') ||
252
+ newPlacement.startsWith('bottom')) {
253
+ const triggerCenter = triggerRect.left + triggerRect.width / 2;
254
+ arrowOffset = triggerCenter - popoverRect.left;
255
+ }
256
+ // If popover is left/right, arrow moves vertically (top)
257
+ else {
258
+ const triggerCenter = triggerRect.top + triggerRect.height / 2;
259
+ arrowOffset = triggerCenter - popoverRect.top;
260
+ }
261
+ // 3. Pass the offset to the content component
262
+ componentRef.instance.arrowOffset = arrowOffset;
263
+ }
264
+ componentRef.changeDetectorRef.detectChanges();
265
+ });
266
+ componentRef.instance.mouseEnterPopover.subscribe(() => {
267
+ if (this.closeTimeout)
268
+ clearTimeout(this.closeTimeout);
269
+ });
270
+ componentRef.instance.mouseLeavePopover.subscribe(() => this.handleMouseLeave());
271
+ if (config.trigger !== 'hover') {
272
+ this.overlayRef.backdropClick().subscribe(() => this.destroy());
273
+ }
274
+ const popoverId = `popover-${Math.random().toString(36).substring(2, 9)}`;
275
+ componentRef.location.nativeElement.setAttribute('id', popoverId);
276
+ trigger.setAttribute('aria-describedby', popoverId);
277
+ this.lastTriggerElement = trigger;
278
+ }
279
+ // Renamed from hide() to destroy() for clarity
280
+ destroy() {
281
+ if (!this.overlayRef)
282
+ return; // Prevent multiple calls
283
+ if (this.lastTriggerElement) {
284
+ this.lastTriggerElement.removeAttribute('aria-describedby');
285
+ this.lastTriggerElement = undefined;
286
+ }
287
+ this.positionSubscription?.unsubscribe();
288
+ this.overlayRef.dispose();
289
+ this.overlayRef = null;
290
+ }
291
+ getPlacementFromPosition(position) {
292
+ if (position.originY === 'top' && position.overlayY === 'bottom')
293
+ return 'top';
294
+ if (position.originY === 'bottom' && position.overlayY === 'top')
295
+ return 'bottom';
296
+ if (position.originX === 'start' && position.overlayX === 'end')
297
+ return 'left';
298
+ if (position.originX === 'end' && position.overlayX === 'start')
299
+ return 'right';
300
+ return 'bottom';
301
+ }
302
+ createPositionStrategy(origin, placement) {
303
+ let preferredPosition;
304
+ switch (placement) {
305
+ case 'top':
306
+ preferredPosition = positions[1];
307
+ break;
308
+ case 'right':
309
+ preferredPosition = positions[2];
310
+ break;
311
+ case 'left':
312
+ preferredPosition = positions[3];
313
+ break;
314
+ default:
315
+ preferredPosition = positions[0];
316
+ break;
317
+ }
318
+ return this.overlay
319
+ .position()
320
+ .flexibleConnectedTo(origin)
321
+ .withPositions([preferredPosition, ...positions])
322
+ .withPush(true);
323
+ }
324
+ //Document-level listeners for closing
325
+ onEscape() {
326
+ this.positionSubscription?.unsubscribe();
327
+ this.serviceSubscription?.unsubscribe();
328
+ this.destroy();
329
+ }
330
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RuclibOverlayComponent, deps: [{ token: i1$1.Overlay }, { token: i0.Injector }, { token: OverlayService }], target: i0.ɵɵFactoryTarget.Component }); }
331
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: RuclibOverlayComponent, isStandalone: true, selector: "uxp-ruclib-overlay", inputs: { buttonText: "buttonText", rucInputData: "rucInputData", customTheme: "customTheme" }, host: { listeners: { "document:keydown:escape": "onEscape()" } }, viewQueries: [{ propertyName: "triggerButtonRef", first: true, predicate: MatButton, descendants: true, read: ElementRef }], ngImport: i0, template: "@if (buttonText) {\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n #triggerButton\r\n (click)=\"toggle()\"\r\n (mouseenter)=\"handleMouseEnter()\"\r\n (mouseleave)=\"handleMouseLeave()\"\r\n class=\"popover-trigger-btn\">\r\n {{ buttonText }}\r\n </button>\r\n}\r\n\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }] }); }
332
+ }
333
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: RuclibOverlayComponent, decorators: [{
334
+ type: Component,
335
+ args: [{ selector: 'uxp-ruclib-overlay', imports: [MatButtonModule, MatIconModule], template: "@if (buttonText) {\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n #triggerButton\r\n (click)=\"toggle()\"\r\n (mouseenter)=\"handleMouseEnter()\"\r\n (mouseleave)=\"handleMouseLeave()\"\r\n class=\"popover-trigger-btn\">\r\n {{ buttonText }}\r\n </button>\r\n}\r\n\r\n" }]
336
+ }], ctorParameters: () => [{ type: i1$1.Overlay }, { type: i0.Injector }, { type: OverlayService }], propDecorators: { buttonText: [{
337
+ type: Input
338
+ }], rucInputData: [{
339
+ type: Input
340
+ }], customTheme: [{
341
+ type: Input
342
+ }], triggerButtonRef: [{
343
+ type: ViewChild,
344
+ args: [MatButton, { read: ElementRef }]
345
+ }], onEscape: [{
346
+ type: HostListener,
347
+ args: ['document:keydown:escape']
348
+ }] } });
349
+
350
+ /**
351
+ * Generated bundle index. Do not edit.
352
+ */
353
+
354
+ export { OVERLAY_CONTROL, OverlayContentComponent, OverlayService, RuclibOverlayComponent };
355
+ //# sourceMappingURL=ruc-lib-overlay.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruc-lib-overlay.mjs","sources":["../../src/lib/model/overlay.types.ts","../../src/lib/service/overlay.service.ts","../../src/lib/ruc-overlay-chart/ruc-overlay-chart.component.ts","../../src/lib/ruc-overlay-chart/ruc-overlay-chart.component.html","../../src/lib/overlay-content/overlay-content.component.ts","../../src/lib/overlay-content/overlay-content.component.html","../../src/lib/constants/positions.ts","../../src/lib/ruclib-overlay/ruclib-overlay.component.ts","../../src/lib/ruclib-overlay/ruclib-overlay.component.html","../../src/ruc-lib-overlay.ts"],"sourcesContent":["import { InjectionToken, TemplateRef } from '@angular/core';\r\n\r\n/**\r\n* Defines the configuration options that a user can pass to the popover.\r\n* This is the public API of your component.\r\n*/\r\nexport interface OverlayConfig {\r\n placement?: 'top' | 'bottom' | 'left' | 'right' | string;\r\n overlayTitle?: string;\r\n content?: string | TemplateRef<any>;\r\n animation?: 'fade' | 'scale';\r\n trigger?: 'click' | 'hover';\r\n showCloseButton?: boolean;\r\n closeIcon?: string;\r\n tableData?: any[];\r\n tableClass?: string;\r\n closeDelay?:number,\r\n chartConfig?:any\r\n}\r\n\r\n/**\r\n* Defines the data packet that the PopoverService sends.\r\n* It contains the configuration AND the element to position against.\r\n* THIS IS THE ONE THE SERVICE USES.\r\n*/\r\nexport interface OverlayData {\r\n config: OverlayConfig;\r\n trigger: HTMLElement;\r\n}\r\n\r\n/**\r\n* Defines the data and controls passed to the dynamically created PopoverContentComponent.\r\n* It includes the config AND a callback function to close the popover.\r\n*/\r\nexport interface OverlayControl {\r\n config: OverlayConfig;\r\n close: () => void;\r\n}\r\n\r\n/**\r\n* The Injection Token used to provide the PopoverControl object to the\r\n* PopoverContentComponent. This is the correct, final version.\r\n*/\r\nexport const OVERLAY_CONTROL = new InjectionToken<OverlayControl>('OVERLAY_CONTROL');\r\n","import { OverlayData } from './../model/overlay.types';\r\nimport { Injectable } from '@angular/core';\r\nimport { Subject } from 'rxjs';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class OverlayService {\r\n\r\n private popoverState = new Subject<OverlayData | null>();\r\n\r\n public popoverState$ = this.popoverState.asObservable();\r\n\r\n\r\n\r\n /**\r\n * Broadcasts a command to open a popover using the OverlayData structure.\r\n */\r\n open(config: OverlayData['config'], trigger: OverlayData['trigger']) {\r\n console.log(config, trigger);\r\n // The service's responsibility is to bundle the config and trigger\r\n // into a PopoverData object and send it.\r\n this.popoverState.next({ config, trigger });\r\n }\r\n\r\n /**\r\n * Broadcasts a command to close any currently open service-controlled popover.\r\n */\r\n close() {\r\n this.popoverState.next(null);\r\n }\r\n}\r\n","import {\r\n AfterViewInit,\r\n ChangeDetectionStrategy,\r\n Component,\r\n Input,\r\n OnDestroy\r\n} from '@angular/core';\r\nimport Chart from 'chart.js/auto';\r\n\r\n\r\n@Component({\r\n selector: 'uxp-ruc-overlay-chart',\r\n imports: [],\r\n templateUrl: './ruc-overlay-chart.component.html',\r\n styleUrl: './ruc-overlay-chart.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class RucOverlayChartComponent implements AfterViewInit, OnDestroy {\r\n chart: any;\r\n @Input() index?:number = 0;\r\n @Input() chartConfig: any;\r\n\r\n ngAfterViewInit(): void {\r\n if(this.chartConfig) {\r\n this.chart = new Chart('canvas' + this.index, this.chartConfig);\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.chart?.destroy();\r\n this.chart = null;\r\n this.chartConfig = null;\r\n }\r\n}\r\n","<div style=\"position: relative; height:220px;\">\r\n <canvas id=\"canvas{{index}}\">{{chart}}</canvas>\r\n</div>\r\n","import { MatIconModule } from '@angular/material/icon';\r\nimport {\r\n Component,\r\n EventEmitter,\r\n HostBinding,\r\n Inject,\r\n Input,\r\n OnInit,\r\n Output,\r\n TemplateRef,\r\n} from '@angular/core';\r\nimport {\r\n animate,\r\n state,\r\n style,\r\n transition,\r\n trigger,\r\n} from '@angular/animations';\r\nimport { OVERLAY_CONTROL, OverlayControl } from '../model/overlay.types';\r\nimport { PopoverPlacement } from '../ruclib-overlay/ruclib-overlay.component';\r\nimport { CommonModule } from '@angular/common';\r\nimport { RucOverlayChartComponent } from '../ruc-overlay-chart/ruc-overlay-chart.component';\r\nimport { MatCardModule } from '@angular/material/card';\r\nimport { MatButtonModule } from '@angular/material/button';\r\n@Component({\r\n selector: 'uxp-overlay-content',\r\n imports: [CommonModule, RucOverlayChartComponent, MatCardModule, MatIconModule, MatButtonModule],\r\n templateUrl: './overlay-content.component.html',\r\n styleUrl: './overlay-content.component.scss',\r\n animations: [\r\n trigger('popoverAnimation', [\r\n state('void', style({ transform: 'scale(0.9)', opacity: 0 })),\r\n state('enter-scale', style({ transform: 'scale(1)', opacity: 1 })),\r\n state('enter-fade', style({ opacity: 1 })),\r\n transition('void => enter-scale', animate('150ms cubic-bezier(0, 0, 0.2, 1)')),\r\n transition('void => enter-fade', [\r\n style({ opacity: 0, transform: 'translateY(10px)' }),\r\n animate('500ms', style({ opacity: 1, transform: 'translateY(0)' })),\r\n ]),\r\n transition('* => void', [\r\n animate('500ms', style({ opacity: 0, transform: 'translateY(10px)' })),\r\n ]),\r\n ]),\r\n ]\r\n})\r\nexport class OverlayContentComponent implements OnInit {\r\n public actualPlacement: string | PopoverPlacement = 'bottom';\r\n public tableHeaders:any[]=[];\r\n @Input() customTheme!:string;\r\n public arrowOffset =0;\r\n\r\n @Output() mouseEnterPopover = new EventEmitter<void>();\r\n @Output() mouseLeavePopover = new EventEmitter<void>();\r\n\r\n\r\n ngOnInit(): void {\r\n if(this.control.config.tableData) {\r\n this.getTableHeaders();\r\n }\r\n }\r\n\r\n @HostBinding('@popoverAnimation')\r\n get animationState() {\r\n return this.control.config.animation === 'scale'\r\n ? 'enter-scale'\r\n : 'enter-fade';\r\n }\r\n\r\n constructor(@Inject(OVERLAY_CONTROL) public control: OverlayControl) {\r\n this.actualPlacement = this.control.config.placement || 'bottom';\r\n }\r\n\r\n // Helper to check if content is a TemplateRef\r\n isTemplateRef(content: any): content is TemplateRef<any> {\r\n return content instanceof TemplateRef;\r\n }\r\n\r\n // Helper to get keys for the table header, robustly\r\n getTableHeaders(): void {\r\n const tempData = this.control.config.tableData;\r\n\r\n if (!tempData || tempData.length === 0) {\r\n this.tableHeaders = [];\r\n return;\r\n }\r\n // Assumes all objects in the array have the same shape\r\n this.tableHeaders = Object.keys(tempData[0]);\r\n }\r\n}\r\n\r\n","<mat-card class=\"popover-container\" class={{customTheme}} (click)=\"$event.stopPropagation()\">\r\n\r\n <div class=\"popover-arrow\"\r\n [attr.data-placement]=\"actualPlacement\"\r\n [style.left.px]=\"(actualPlacement.startsWith('top') || actualPlacement.startsWith('bottom')) ? arrowOffset : null\"\r\n [style.top.px]=\"(actualPlacement.startsWith('left') || actualPlacement.startsWith('right')) ? arrowOffset : null\">\r\n </div>\r\n <!-- Header with optional title and close button -->\r\n\r\n @if (\r\n control.config.overlayTitle ||\r\n control.config.showCloseButton ||\r\n control.config.closeIcon\r\n ) {\r\n <mat-card-header\r\n class=\"popover-header\"\r\n >\r\n @if (control.config.overlayTitle) {\r\n <mat-card-title class=\"popover-title\">{{ control.config.overlayTitle }}</mat-card-title>\r\n }\r\n @if (control.config.showCloseButton && control.config.closeIcon) {\r\n <button mat-icon-button class=\"close-btn\" (click)=\"control.close()\" color=\"primary\" aria-label=\"Close popover icon\">\r\n <mat-icon>{{ control.config.closeIcon }}</mat-icon>\r\n </button>\r\n }\r\n </mat-card-header>\r\n }\r\n\r\n\r\n <!-- Body with dynamic content -->\r\n <mat-card-content class=\"popover-body\">\r\n <!-- Case 1: Content is a simple string -->\r\n @if (\r\n !isTemplateRef(control.config.content) && !control.config.tableData\r\n ) {\r\n {{ control.config.content }}\r\n }\r\n\r\n <!-- Case 2: Content is a TemplateRef -->\r\n @if (isTemplateRef(control.config.content)) {\r\n <ng-container *ngTemplateOutlet=\"control.config.content\"></ng-container>\r\n }\r\n\r\n @if (control.config.chartConfig) {\r\n <uxp-ruc-overlay-chart [chartConfig]=\"control.config.chartConfig\"></uxp-ruc-overlay-chart>\r\n }\r\n\r\n <!-- Case 3: Content is table data -->\r\n @if (control.config.tableData?.length) {\r\n <table\r\n class=\"popover-table\"\r\n [class]=\"control.config.tableClass || 'basic-table'\"\r\n >\r\n <thead>\r\n <tr>\r\n @for (header of this.tableHeaders!; track header) {\r\n <th\r\n >\r\n {{ header }}\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n <tbody>\r\n @for (row of control.config.tableData; track row) {\r\n <tr>\r\n @for (header of this.tableHeaders!; track header) {\r\n <td\r\n >\r\n {{ row[header] }}\r\n </td>\r\n }\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n }\r\n </mat-card-content>\r\n</mat-card>\r\n","import { ConnectedPosition } from \"@angular/cdk/overlay\";\r\n\r\nexport const positions: ConnectedPosition[] = [\r\n { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 10 },\r\n { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -10 },\r\n { originX: 'end', originY: 'center', overlayX: 'start', overlayY: 'center', offsetX: 10 },\r\n { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center', offsetX: -10 }\r\n ];\r\n","import {\r\n ConnectedPosition,\r\n ConnectionPositionPair,\r\n FlexibleConnectedPositionStrategy,\r\n Overlay,\r\n OverlayRef,\r\n} from '@angular/cdk/overlay';\r\nimport {\r\n Component,\r\n ElementRef,\r\n HostListener,\r\n Injector,\r\n Input,\r\n OnDestroy,\r\n OnInit,\r\n ViewChild,\r\n} from '@angular/core';\r\nimport {\r\n OVERLAY_CONTROL,\r\n OverlayConfig,\r\n OverlayControl,\r\n OverlayData,\r\n} from '../model/overlay.types';\r\nimport { filter, Subscription } from 'rxjs';\r\nimport { ComponentPortal } from '@angular/cdk/portal';\r\nimport { OverlayService } from '../service/overlay.service';\r\nimport { OverlayContentComponent } from '../overlay-content/overlay-content.component';\r\nimport { MatButton, MatButtonModule } from '@angular/material/button';\r\nimport { ESCAPE } from '@angular/cdk/keycodes';\r\nimport { positions } from '../constants/positions';\r\n\r\nexport type PopoverPlacement = 'top' | 'bottom' | 'left' | 'right';\r\nexport type PopoverAnimation = 'fade' | 'scale';\r\nexport type ChartType = 'doughnut' | 'pie' | 'bar';\r\n\r\nexport interface ChartModel {\r\n chartType: ChartType;\r\n data: any;\r\n}\r\n\r\n\r\nimport { MatIconModule } from '@angular/material/icon';\r\n\r\n@Component({\r\n selector: 'uxp-ruclib-overlay',\r\n imports: [MatButtonModule, MatIconModule],\r\n templateUrl: './ruclib-overlay.component.html',\r\n styleUrl: './ruclib-overlay.component.scss'\r\n})\r\nexport class RuclibOverlayComponent implements OnInit, OnDestroy {\r\n @Input() buttonText?: string;\r\n @Input() rucInputData: OverlayConfig = {\r\n content: 'Default content',\r\n };\r\n @Input() customTheme!: string;\r\n\r\n @ViewChild(MatButton, { read: ElementRef })\r\n private triggerButtonRef!: ElementRef;\r\n\r\n private overlayRef: OverlayRef | null = null;\r\n private serviceSubscription!: Subscription;\r\n private closeTimeout?: ReturnType<typeof setTimeout>; // Use the correct type\r\n private lastTriggerElement?: HTMLElement;\r\n private positionSubscription!: Subscription;\r\n\r\n constructor(\r\n private overlay: Overlay,\r\n private injector: Injector,\r\n private overlayService: OverlayService\r\n ) {}\r\n\r\n ngOnInit(): void {\r\n if (!this.buttonText) {\r\n this.serviceSubscription = this.overlayService.popoverState$.subscribe(\r\n (data: any) => {\r\n if (data && !this.isOpen) {\r\n this.show(data.trigger, data.config);\r\n } else if (!data) {\r\n this.destroy();\r\n }\r\n }\r\n );\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.positionSubscription?.unsubscribe();\r\n this.serviceSubscription?.unsubscribe();\r\n this.destroy();\r\n }\r\n\r\n get isOpen(): boolean {\r\n return !!this.overlayRef;\r\n }\r\n\r\n // --- Trigger Handlers for self-contained button ---\r\n toggle(): void {\r\n if (this.rucInputData.trigger !== 'hover') {\r\n this.isOpen\r\n ? this.destroy()\r\n : this.show(this.triggerButtonRef.nativeElement, this.rucInputData);\r\n }\r\n }\r\n\r\n handleMouseEnter(): void {\r\n if (this.rucInputData.trigger === 'hover') {\r\n if (this.closeTimeout) clearTimeout(this.closeTimeout); // Clear any pending close command\r\n this.show(this.triggerButtonRef.nativeElement, this.rucInputData);\r\n }\r\n }\r\n\r\n handleMouseLeave(): void {\r\n if (this.rucInputData.trigger === 'hover') {\r\n // Use the configurable closeDelay\r\n const delay = this.rucInputData.closeDelay ?? 200;\r\n this.closeTimeout = setTimeout(() => this.destroy(), delay);\r\n }\r\n }\r\n\r\n private show(trigger: HTMLElement, config: OverlayConfig): void {\r\n if (this.isOpen) return;\r\n\r\n const positionStrategy = this.createPositionStrategy(\r\n trigger,\r\n config.placement || 'bottom'\r\n );\r\n this.overlayRef = this.overlay.create({\r\n positionStrategy,\r\n hasBackdrop: config.trigger !== 'hover',\r\n backdropClass: 'cdk-overlay-transparent-backdrop',\r\n scrollStrategy: this.overlay.scrollStrategies.reposition(),\r\n });\r\n\r\n this.overlayRef.keydownEvents().pipe(filter(event=> event.keyCode === ESCAPE)).subscribe(()=> this.destroy());\r\n\r\n const control: OverlayControl = { config, close: this.destroy.bind(this) };\r\n const injector = Injector.create({\r\n parent: this.injector,\r\n providers: [{ provide: OVERLAY_CONTROL, useValue: control }],\r\n });\r\n\r\n const portal = new ComponentPortal(OverlayContentComponent, null, injector);\r\n const componentRef = this.overlayRef.attach(portal);\r\n componentRef.instance.customTheme = this.customTheme;\r\n\r\n // --- START: MODIFICATION FOR DYNAMIC ARROW ---\r\n this.positionSubscription = positionStrategy.positionChanges.subscribe(\r\n (change) => {\r\n // 1. Get the new placement ('top', 'bottom', etc.)\r\n const newPlacement = this.getPlacementFromPosition(\r\n change.connectionPair\r\n );\r\n componentRef.instance.actualPlacement = newPlacement;\r\n\r\n // 2. Calculate the arrow's offset\r\n if (this.overlayRef) {\r\n const triggerRect = trigger.getBoundingClientRect();\r\n const popoverRect =\r\n this.overlayRef.overlayElement.getBoundingClientRect();\r\n\r\n let arrowOffset = 0;\r\n // If popover is top/bottom, arrow moves horizontally (left)\r\n if (\r\n newPlacement.startsWith('top') ||\r\n newPlacement.startsWith('bottom')\r\n ) {\r\n const triggerCenter = triggerRect.left + triggerRect.width / 2;\r\n arrowOffset = triggerCenter - popoverRect.left;\r\n }\r\n // If popover is left/right, arrow moves vertically (top)\r\n else {\r\n const triggerCenter = triggerRect.top + triggerRect.height / 2;\r\n arrowOffset = triggerCenter - popoverRect.top;\r\n }\r\n\r\n // 3. Pass the offset to the content component\r\n componentRef.instance.arrowOffset = arrowOffset;\r\n }\r\n\r\n componentRef.changeDetectorRef.detectChanges();\r\n }\r\n );\r\n\r\n componentRef.instance.mouseEnterPopover.subscribe(() => {\r\n if (this.closeTimeout) clearTimeout(this.closeTimeout);\r\n });\r\n componentRef.instance.mouseLeavePopover.subscribe(() =>\r\n this.handleMouseLeave()\r\n );\r\n\r\n if (config.trigger !== 'hover') {\r\n this.overlayRef.backdropClick().subscribe(() => this.destroy());\r\n }\r\n\r\n const popoverId = `popover-${Math.random().toString(36).substring(2, 9)}`;\r\n componentRef.location.nativeElement.setAttribute('id', popoverId);\r\n trigger.setAttribute('aria-describedby', popoverId);\r\n this.lastTriggerElement = trigger;\r\n }\r\n\r\n // Renamed from hide() to destroy() for clarity\r\n private destroy(): void {\r\n if (!this.overlayRef) return; // Prevent multiple calls\r\n\r\n if (this.lastTriggerElement) {\r\n this.lastTriggerElement.removeAttribute('aria-describedby');\r\n this.lastTriggerElement = undefined;\r\n }\r\n this.positionSubscription?.unsubscribe();\r\n this.overlayRef.dispose();\r\n this.overlayRef = null;\r\n }\r\n\r\n private getPlacementFromPosition(\r\n position: ConnectionPositionPair\r\n ): PopoverPlacement {\r\n if (position.originY === 'top' && position.overlayY === 'bottom')\r\n return 'top';\r\n if (position.originY === 'bottom' && position.overlayY === 'top')\r\n return 'bottom';\r\n if (position.originX === 'start' && position.overlayX === 'end')\r\n return 'left';\r\n if (position.originX === 'end' && position.overlayX === 'start')\r\n return 'right';\r\n return 'bottom';\r\n }\r\n\r\n private createPositionStrategy(\r\n origin: HTMLElement,\r\n placement: string\r\n ): FlexibleConnectedPositionStrategy {\r\n let preferredPosition: ConnectedPosition;\r\n switch (placement) {\r\n case 'top':\r\n preferredPosition = positions[1];\r\n break;\r\n case 'right':\r\n preferredPosition = positions[2];\r\n break;\r\n case 'left':\r\n preferredPosition = positions[3];\r\n break;\r\n default:\r\n preferredPosition = positions[0];\r\n break;\r\n }\r\n\r\n return this.overlay\r\n .position()\r\n .flexibleConnectedTo(origin)\r\n .withPositions([preferredPosition, ...positions])\r\n .withPush(true);\r\n }\r\n\r\n //Document-level listeners for closing\r\n @HostListener('document:keydown:escape')\r\n onEscape(): void {\r\n this.positionSubscription?.unsubscribe();\r\n this.serviceSubscription?.unsubscribe();\r\n this.destroy();\r\n }\r\n}\r\n","@if (buttonText) {\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n #triggerButton\r\n (click)=\"toggle()\"\r\n (mouseenter)=\"handleMouseEnter()\"\r\n (mouseleave)=\"handleMouseLeave()\"\r\n class=\"popover-trigger-btn\">\r\n {{ buttonText }}\r\n </button>\r\n}\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2.OverlayService","i3"],"mappings":"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"}