ng-auto-position 0.0.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 +27 -0
- package/app/ng-auto-position/ng-auto-position.directive.d.ts +73 -0
- package/esm2022/app/ng-auto-position/ng-auto-position.directive.mjs +161 -0
- package/esm2022/ng-auto-position.mjs +5 -0
- package/esm2022/public_api.mjs +2 -0
- package/fesm2022/ng-auto-position.mjs +168 -0
- package/fesm2022/ng-auto-position.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/ng-auto-position-0.0.0.tgz +0 -0
- package/package.json +33 -0
- package/public_api.d.ts +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# NgAutoPosition
|
|
2
|
+
|
|
3
|
+
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.7.
|
|
4
|
+
|
|
5
|
+
## Development server
|
|
6
|
+
|
|
7
|
+
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
|
|
8
|
+
|
|
9
|
+
## Code scaffolding
|
|
10
|
+
|
|
11
|
+
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
|
|
12
|
+
|
|
13
|
+
## Build
|
|
14
|
+
|
|
15
|
+
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
16
|
+
|
|
17
|
+
## Running unit tests
|
|
18
|
+
|
|
19
|
+
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
20
|
+
|
|
21
|
+
## Running end-to-end tests
|
|
22
|
+
|
|
23
|
+
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
|
|
24
|
+
|
|
25
|
+
## Further help
|
|
26
|
+
|
|
27
|
+
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { AfterViewInit } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* AutoPositionElementDirective
|
|
5
|
+
*
|
|
6
|
+
* Automatically positions an overlay element (dropdown / popover)
|
|
7
|
+
* relative to a reference element and keeps it inside the viewport.
|
|
8
|
+
*
|
|
9
|
+
* DESIGN DECISIONS:
|
|
10
|
+
* - Uses `position: fixed` so viewport math is reliable.
|
|
11
|
+
* - Uses getBoundingClientRect() for all measurements.
|
|
12
|
+
* - Avoids DOM depth assumptions (npm-safe).
|
|
13
|
+
* - Uses ResizeObserver to react to size changes.
|
|
14
|
+
*/
|
|
15
|
+
export declare class NgAutoPositionElementDirective implements AfterViewInit {
|
|
16
|
+
/** Native element reference for the overlay */
|
|
17
|
+
private readonly el;
|
|
18
|
+
/** Used by Angular to auto-clean RxJS subscriptions */
|
|
19
|
+
private readonly destroyRef;
|
|
20
|
+
/**
|
|
21
|
+
* ID of the reference element.
|
|
22
|
+
* If not provided, parentElement is used.
|
|
23
|
+
*/
|
|
24
|
+
referenceElementId: import("@angular/core").InputSignal<string>;
|
|
25
|
+
/** Debounce time for scroll / resize events (ms) */
|
|
26
|
+
debounceMs: import("@angular/core").InputSignal<number>;
|
|
27
|
+
/** Gap between reference and overlay (px) */
|
|
28
|
+
offset: import("@angular/core").InputSignal<number>;
|
|
29
|
+
/** Match overlay width to reference width */
|
|
30
|
+
matchWidth: import("@angular/core").InputSignal<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Optional selector for inner scrollable content
|
|
33
|
+
* whose max-height will be auto-calculated.
|
|
34
|
+
*/
|
|
35
|
+
scrollableSelector: import("@angular/core").InputSignal<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Enables or disables automatic repositioning
|
|
38
|
+
* on window scroll and resize.
|
|
39
|
+
*
|
|
40
|
+
* Default: true
|
|
41
|
+
*/
|
|
42
|
+
enableAutoReposition: import("@angular/core").InputSignal<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* List of element IDs or class names
|
|
45
|
+
* whose scrollbars should be hidden
|
|
46
|
+
* while the popup is visible.
|
|
47
|
+
*
|
|
48
|
+
* Examples:
|
|
49
|
+
* ['body']
|
|
50
|
+
* ['app-layout', '.content-wrapper']
|
|
51
|
+
*/
|
|
52
|
+
hideScrollTargets: import("@angular/core").InputSignal<string[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Hide overlay until positioned to avoid flicker.
|
|
55
|
+
*/
|
|
56
|
+
visibility: 'hidden' | 'visible';
|
|
57
|
+
ngAfterViewInit(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Returns true if the reference element is completely outside viewport.
|
|
60
|
+
* Even 1px visible = considered visible.
|
|
61
|
+
*/
|
|
62
|
+
private isReferenceFullyOut;
|
|
63
|
+
/**
|
|
64
|
+
* Calculates and applies overlay position.
|
|
65
|
+
*/
|
|
66
|
+
private updatePosition;
|
|
67
|
+
/**
|
|
68
|
+
* Resolves the reference element.
|
|
69
|
+
*/
|
|
70
|
+
private getReferenceElement;
|
|
71
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NgAutoPositionElementDirective, never>;
|
|
72
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<NgAutoPositionElementDirective, "[ngAutoPosition]", never, { "referenceElementId": { "alias": "referenceElementId"; "required": false; "isSignal": true; }; "debounceMs": { "alias": "debounceMs"; "required": false; "isSignal": true; }; "offset": { "alias": "offset"; "required": false; "isSignal": true; }; "matchWidth": { "alias": "matchWidth"; "required": false; "isSignal": true; }; "scrollableSelector": { "alias": "scrollableSelector"; "required": false; "isSignal": true; }; "enableAutoReposition": { "alias": "enableAutoReposition"; "required": false; "isSignal": true; }; "hideScrollTargets": { "alias": "hideScrollTargets"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
73
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { DestroyRef, Directive, ElementRef, HostBinding, inject, input, } from '@angular/core';
|
|
2
|
+
import { fromEvent, merge } from 'rxjs';
|
|
3
|
+
import { debounceTime } from 'rxjs/operators';
|
|
4
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* AutoPositionElementDirective
|
|
8
|
+
*
|
|
9
|
+
* Automatically positions an overlay element (dropdown / popover)
|
|
10
|
+
* relative to a reference element and keeps it inside the viewport.
|
|
11
|
+
*
|
|
12
|
+
* DESIGN DECISIONS:
|
|
13
|
+
* - Uses `position: fixed` so viewport math is reliable.
|
|
14
|
+
* - Uses getBoundingClientRect() for all measurements.
|
|
15
|
+
* - Avoids DOM depth assumptions (npm-safe).
|
|
16
|
+
* - Uses ResizeObserver to react to size changes.
|
|
17
|
+
*/
|
|
18
|
+
export class NgAutoPositionElementDirective {
|
|
19
|
+
/** Native element reference for the overlay */
|
|
20
|
+
el = inject((ElementRef));
|
|
21
|
+
/** Used by Angular to auto-clean RxJS subscriptions */
|
|
22
|
+
destroyRef = inject(DestroyRef);
|
|
23
|
+
/**
|
|
24
|
+
* ID of the reference element.
|
|
25
|
+
* If not provided, parentElement is used.
|
|
26
|
+
*/
|
|
27
|
+
referenceElementId = input(null);
|
|
28
|
+
/** Debounce time for scroll / resize events (ms) */
|
|
29
|
+
debounceMs = input(0);
|
|
30
|
+
/** Gap between reference and overlay (px) */
|
|
31
|
+
offset = input(5);
|
|
32
|
+
/** Match overlay width to reference width */
|
|
33
|
+
matchWidth = input(false);
|
|
34
|
+
/**
|
|
35
|
+
* Optional selector for inner scrollable content
|
|
36
|
+
* whose max-height will be auto-calculated.
|
|
37
|
+
*/
|
|
38
|
+
scrollableSelector = input(null);
|
|
39
|
+
/**
|
|
40
|
+
* Enables or disables automatic repositioning
|
|
41
|
+
* on window scroll and resize.
|
|
42
|
+
*
|
|
43
|
+
* Default: true
|
|
44
|
+
*/
|
|
45
|
+
enableAutoReposition = input(true);
|
|
46
|
+
/**
|
|
47
|
+
* List of element IDs or class names
|
|
48
|
+
* whose scrollbars should be hidden
|
|
49
|
+
* while the popup is visible.
|
|
50
|
+
*
|
|
51
|
+
* Examples:
|
|
52
|
+
* ['body']
|
|
53
|
+
* ['app-layout', '.content-wrapper']
|
|
54
|
+
*/
|
|
55
|
+
hideScrollTargets = input(null);
|
|
56
|
+
/**
|
|
57
|
+
* Hide overlay until positioned to avoid flicker.
|
|
58
|
+
*/
|
|
59
|
+
visibility = 'hidden';
|
|
60
|
+
ngAfterViewInit() {
|
|
61
|
+
const overlay = this.el.nativeElement;
|
|
62
|
+
overlay.style.position = 'fixed';
|
|
63
|
+
// ResizeObserver always useful (content changes)
|
|
64
|
+
const ro = new ResizeObserver(() => this.updatePosition());
|
|
65
|
+
ro.observe(overlay);
|
|
66
|
+
const reference = this.getReferenceElement(overlay);
|
|
67
|
+
if (reference)
|
|
68
|
+
ro.observe(reference);
|
|
69
|
+
// Conditionally listen to scroll + resize
|
|
70
|
+
if (this.enableAutoReposition()) {
|
|
71
|
+
merge(fromEvent(window, 'scroll'), fromEvent(window, 'resize'))
|
|
72
|
+
.pipe(debounceTime(this.debounceMs()), takeUntilDestroyed(this.destroyRef))
|
|
73
|
+
.subscribe(() => this.updatePosition());
|
|
74
|
+
}
|
|
75
|
+
this.updatePosition();
|
|
76
|
+
this.destroyRef.onDestroy?.(() => ro.disconnect());
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Returns true if the reference element is completely outside viewport.
|
|
80
|
+
* Even 1px visible = considered visible.
|
|
81
|
+
*/
|
|
82
|
+
isReferenceFullyOut(refRect) {
|
|
83
|
+
const vw = window.innerWidth;
|
|
84
|
+
const vh = window.innerHeight;
|
|
85
|
+
return (refRect.bottom <= 0 || // above viewport
|
|
86
|
+
refRect.top >= vh || // below viewport
|
|
87
|
+
refRect.right <= 0 || // left of viewport
|
|
88
|
+
refRect.left >= vw // right of viewport
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Calculates and applies overlay position.
|
|
93
|
+
*/
|
|
94
|
+
updatePosition() {
|
|
95
|
+
const overlay = this.el.nativeElement;
|
|
96
|
+
const reference = this.getReferenceElement(overlay);
|
|
97
|
+
if (!reference)
|
|
98
|
+
return;
|
|
99
|
+
const viewportW = window.innerWidth;
|
|
100
|
+
const viewportH = window.innerHeight;
|
|
101
|
+
const refRect = reference.getBoundingClientRect();
|
|
102
|
+
// Optionally match width
|
|
103
|
+
if (this.matchWidth()) {
|
|
104
|
+
overlay.style.width = `${refRect.width}px`;
|
|
105
|
+
}
|
|
106
|
+
const overlayRect = overlay.getBoundingClientRect();
|
|
107
|
+
const spaceAbove = refRect.top;
|
|
108
|
+
const spaceBelow = viewportH - refRect.bottom;
|
|
109
|
+
const openOnTop = overlayRect.height > spaceBelow && spaceAbove >= overlayRect.height;
|
|
110
|
+
// --- base positioning relative to reference ---
|
|
111
|
+
let top = openOnTop
|
|
112
|
+
? refRect.top - overlayRect.height - this.offset()
|
|
113
|
+
: refRect.bottom + this.offset();
|
|
114
|
+
let left = refRect.left;
|
|
115
|
+
const fullyOut = this.isReferenceFullyOut(refRect);
|
|
116
|
+
if (!fullyOut) {
|
|
117
|
+
// ✅ NORMAL MODE (reference at least partially visible)
|
|
118
|
+
// Clamp to viewport
|
|
119
|
+
top = Math.min(top, viewportH - overlayRect.height - 4);
|
|
120
|
+
left = Math.min(left, viewportW - overlayRect.width - 4);
|
|
121
|
+
}
|
|
122
|
+
// else: ✅ FOLLOW MODE (reference fully out of viewport)
|
|
123
|
+
// do NOT clamp → let popup go offscreen naturally
|
|
124
|
+
// top & left stay relative to refRect
|
|
125
|
+
overlay.style.top = `${top}px`;
|
|
126
|
+
overlay.style.left = `${left}px`;
|
|
127
|
+
// Optional inner scroll container handling
|
|
128
|
+
if (this.scrollableSelector()) {
|
|
129
|
+
const inner = overlay.querySelector(this.scrollableSelector());
|
|
130
|
+
if (inner) {
|
|
131
|
+
const maxSpace = openOnTop ? spaceAbove : spaceBelow;
|
|
132
|
+
inner.style.maxHeight = `${Math.min(maxSpace - 10, viewportH * 0.9)}px`;
|
|
133
|
+
inner.style.overflowY = 'auto';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// visibility safe update
|
|
137
|
+
queueMicrotask(() => {
|
|
138
|
+
this.visibility = 'visible';
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Resolves the reference element.
|
|
143
|
+
*/
|
|
144
|
+
getReferenceElement(overlay) {
|
|
145
|
+
const id = this.referenceElementId();
|
|
146
|
+
return id ? document.getElementById(id) : overlay.parentElement;
|
|
147
|
+
}
|
|
148
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgAutoPositionElementDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
149
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "17.3.12", type: NgAutoPositionElementDirective, isStandalone: true, selector: "[ngAutoPosition]", inputs: { referenceElementId: { classPropertyName: "referenceElementId", publicName: "referenceElementId", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, matchWidth: { classPropertyName: "matchWidth", publicName: "matchWidth", isSignal: true, isRequired: false, transformFunction: null }, scrollableSelector: { classPropertyName: "scrollableSelector", publicName: "scrollableSelector", isSignal: true, isRequired: false, transformFunction: null }, enableAutoReposition: { classPropertyName: "enableAutoReposition", publicName: "enableAutoReposition", isSignal: true, isRequired: false, transformFunction: null }, hideScrollTargets: { classPropertyName: "hideScrollTargets", publicName: "hideScrollTargets", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.visibility": "this.visibility" } }, ngImport: i0 });
|
|
150
|
+
}
|
|
151
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgAutoPositionElementDirective, decorators: [{
|
|
152
|
+
type: Directive,
|
|
153
|
+
args: [{
|
|
154
|
+
selector: '[ngAutoPosition]',
|
|
155
|
+
standalone: true,
|
|
156
|
+
}]
|
|
157
|
+
}], propDecorators: { visibility: [{
|
|
158
|
+
type: HostBinding,
|
|
159
|
+
args: ['style.visibility']
|
|
160
|
+
}] } });
|
|
161
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctYXV0by1wb3NpdGlvbi5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvYXBwL25nLWF1dG8tcG9zaXRpb24vbmctYXV0by1wb3NpdGlvbi5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLFVBQVUsRUFDVixTQUFTLEVBQ1QsVUFBVSxFQUNWLFdBQVcsRUFDWCxNQUFNLEVBQ04sS0FBSyxHQUNOLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7QUFFaEU7Ozs7Ozs7Ozs7O0dBV0c7QUFLSCxNQUFNLE9BQU8sOEJBQThCO0lBQ3pDLCtDQUErQztJQUM5QixFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUEsVUFBdUIsQ0FBQSxDQUFDLENBQUM7SUFFdEQsdURBQXVEO0lBQ3RDLFVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFFakQ7OztPQUdHO0lBQ0gsa0JBQWtCLEdBQUcsS0FBSyxDQUFnQixJQUFJLENBQUMsQ0FBQztJQUVoRCxvREFBb0Q7SUFDcEQsVUFBVSxHQUFHLEtBQUssQ0FBUyxDQUFDLENBQUMsQ0FBQztJQUU5Qiw2Q0FBNkM7SUFDN0MsTUFBTSxHQUFHLEtBQUssQ0FBUyxDQUFDLENBQUMsQ0FBQztJQUUxQiw2Q0FBNkM7SUFDN0MsVUFBVSxHQUFHLEtBQUssQ0FBVSxLQUFLLENBQUMsQ0FBQztJQUVuQzs7O09BR0c7SUFDSCxrQkFBa0IsR0FBRyxLQUFLLENBQWdCLElBQUksQ0FBQyxDQUFDO0lBRWhEOzs7OztPQUtHO0lBQ0gsb0JBQW9CLEdBQUcsS0FBSyxDQUFVLElBQUksQ0FBQyxDQUFDO0lBRTVD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LFNBQVMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7Z0JBQ3JELEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEdBQUcsRUFBRSxFQUFFLFNBQVMsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO2dCQUN4RSxLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUM7WUFDakMsQ0FBQztRQUNILENBQUM7UUFFRCx5QkFBeUI7UUFDekIsY0FBYyxDQUFDLEdBQUcsRUFBRTtZQUNsQixJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLG1CQUFtQixDQUFDLE9BQW9CO1FBQzlDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQ3JDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDO0lBQ2xFLENBQUM7d0dBeEtVLDhCQUE4Qjs0RkFBOUIsOEJBQThCOzs0RkFBOUIsOEJBQThCO2tCQUoxQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxrQkFBa0I7b0JBQzVCLFVBQVUsRUFBRSxJQUFJO2lCQUNqQjs4QkFvREMsVUFBVTtzQkFEVCxXQUFXO3VCQUFDLGtCQUFrQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBEZXN0cm95UmVmLFxyXG4gIERpcmVjdGl2ZSxcclxuICBFbGVtZW50UmVmLFxyXG4gIEhvc3RCaW5kaW5nLFxyXG4gIGluamVjdCxcclxuICBpbnB1dCxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgZnJvbUV2ZW50LCBtZXJnZSB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcclxuXHJcbi8qKlxyXG4gKiBBdXRvUG9zaXRpb25FbGVtZW50RGlyZWN0aXZlXHJcbiAqXHJcbiAqIEF1dG9tYXRpY2FsbHkgcG9zaXRpb25zIGFuIG92ZXJsYXkgZWxlbWVudCAoZHJvcGRvd24gLyBwb3BvdmVyKVxyXG4gKiByZWxhdGl2ZSB0byBhIHJlZmVyZW5jZSBlbGVtZW50IGFuZCBrZWVwcyBpdCBpbnNpZGUgdGhlIHZpZXdwb3J0LlxyXG4gKlxyXG4gKiBERVNJR04gREVDSVNJT05TOlxyXG4gKiAtIFVzZXMgYHBvc2l0aW9uOiBmaXhlZGAgc28gdmlld3BvcnQgbWF0aCBpcyByZWxpYWJsZS5cclxuICogLSBVc2VzIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpIGZvciBhbGwgbWVhc3VyZW1lbnRzLlxyXG4gKiAtIEF2b2lkcyBET00gZGVwdGggYXNzdW1wdGlvbnMgKG5wbS1zYWZlKS5cclxuICogLSBVc2VzIFJlc2l6ZU9ic2VydmVyIHRvIHJlYWN0IHRvIHNpemUgY2hhbmdlcy5cclxuICovXHJcbkBEaXJlY3RpdmUoe1xyXG4gIHNlbGVjdG9yOiAnW25nQXV0b1Bvc2l0aW9uXScsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxufSlcclxuZXhwb3J0IGNsYXNzIE5nQXV0b1Bvc2l0aW9uRWxlbWVudERpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xyXG4gIC8qKiBOYXRpdmUgZWxlbWVudCByZWZlcmVuY2UgZm9yIHRoZSBvdmVybGF5ICovXHJcbiAgcHJpdmF0ZSByZWFkb25seSBlbCA9IGluamVjdChFbGVtZW50UmVmPEhUTUxFbGVtZW50Pik7XHJcblxyXG4gIC8qKiBVc2VkIGJ5IEFuZ3VsYXIgdG8gYXV0by1jbGVhbiBSeEpTIHN1YnNjcmlwdGlvbnMgKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XHJcblxyXG4gIC8qKlxyXG4gICAqIElEIG9mIHRoZSByZWZlcmVuY2UgZWxlbWVudC5cclxuICAgKiBJZiBub3QgcHJvdmlkZWQsIHBhcmVudEVsZW1lbnQgaXMgdXNlZC5cclxuICAgKi9cclxuICByZWZlcmVuY2VFbGVtZW50SWQgPSBpbnB1dDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuXHJcbiAgLyoqIERlYm91bmNlIHRpbWUgZm9yIHNjcm9sbCAvIHJlc2l6ZSBldmVudHMgKG1zKSAqL1xyXG4gIGRlYm91bmNlTXMgPSBpbnB1dDxudW1iZXI+KDApO1xyXG5cclxuICAvKiogR2FwIGJldHdlZW4gcmVmZXJlbmNlIGFuZCBvdmVybGF5IChweCkgKi9cclxuICBvZmZzZXQgPSBpbnB1dDxudW1iZXI+KDUpO1xyXG5cclxuICAvKiogTWF0Y2ggb3ZlcmxheSB3aWR0aCB0byByZWZlcmVuY2Ugd2lkdGggKi9cclxuICBtYXRjaFdpZHRoID0gaW5wdXQ8Ym9vbGVhbj4oZmFsc2UpO1xyXG5cclxuICAvKipcclxuICAgKiBPcHRpb25hbCBzZWxlY3RvciBmb3IgaW5uZXIgc2Nyb2xsYWJsZSBjb250ZW50XHJcbiAgICogd2hvc2UgbWF4LWhlaWdodCB3aWxsIGJlIGF1dG8tY2FsY3VsYXRlZC5cclxuICAgKi9cclxuICBzY3JvbGxhYmxlU2VsZWN0b3IgPSBpbnB1dDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRW5hYmxlcyBvciBkaXNhYmxlcyBhdXRvbWF0aWMgcmVwb3NpdGlvbmluZ1xyXG4gICAqIG9uIHdpbmRvdyBzY3JvbGwgYW5kIHJlc2l6ZS5cclxuICAgKlxyXG4gICAqIERlZmF1bHQ6IHRydWVcclxuICAgKi9cclxuICBlbmFibGVBdXRvUmVwb3NpdGlvbiA9IGlucHV0PGJvb2xlYW4+KHRydWUpO1xyXG5cclxuICAvKipcclxuICAgKiBMaXN0IG9mIGVsZW1lbnQgSURzIG9yIGNsYXNzIG5hbWVzXHJcbiAgICogd2hvc2Ugc2Nyb2xsYmFycyBzaG91bGQgYmUgaGlkZGVuXHJcbiAgICogd2hpbGUgdGhlIHBvcHVwIGlzIHZpc2libGUuXHJcbiAgICpcclxuICAgKiBFeGFtcGxlczpcclxuICAgKiBbJ2JvZHknXVxyXG4gICAqIFsnYXBwLWxheW91dCcsICcuY29udGVudC13cmFwcGVyJ11cclxuICAgKi9cclxuICBoaWRlU2Nyb2xsVGFyZ2V0cyA9IGlucHV0PHN0cmluZ1tdIHwgbnVsbD4obnVsbCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEhpZGUgb3ZlcmxheSB1bnRpbCBwb3NpdGlvbmVkIHRvIGF2b2lkIGZsaWNrZXIuXHJcbiAgICovXHJcbiAgQEhvc3RCaW5kaW5nKCdzdHlsZS52aXNpYmlsaXR5JylcclxuICB2aXNpYmlsaXR5OiAnaGlkZGVuJyB8ICd2aXNpYmxlJyA9ICdoaWRkZW4nO1xyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XHJcbiAgICBjb25zdCBvdmVybGF5ID0gdGhpcy5lbC5uYXRpdmVFbGVtZW50O1xyXG4gICAgb3ZlcmxheS5zdHlsZS5wb3NpdGlvbiA9ICdmaXhlZCc7XHJcblxyXG4gICAgLy8gUmVzaXplT2JzZXJ2ZXIgYWx3YXlzIHVzZWZ1bCAoY29udGVudCBjaGFuZ2VzKVxyXG4gICAgY29uc3Qgcm8gPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4gdGhpcy51cGRhdGVQb3NpdGlvbigpKTtcclxuICAgIHJvLm9ic2VydmUob3ZlcmxheSk7XHJcblxyXG4gICAgY29uc3QgcmVmZXJlbmNlID0gdGhpcy5nZXRSZWZlcmVuY2VFbGVtZW50KG92ZXJsYXkpO1xyXG4gICAgaWYgKHJlZmVyZW5jZSkgcm8ub2JzZXJ2ZShyZWZlcmVuY2UpO1xyXG5cclxuICAgIC8vIENvbmRpdGlvbmFsbHkgbGlzdGVuIHRvIHNjcm9sbCArIHJlc2l6ZVxyXG4gICAgaWYgKHRoaXMuZW5hYmxlQXV0b1JlcG9zaXRpb24oKSkge1xyXG4gICAgICBtZXJnZShmcm9tRXZlbnQod2luZG93LCAnc2Nyb2xsJyksIGZyb21FdmVudCh3aW5kb3csICdyZXNpemUnKSlcclxuICAgICAgICAucGlwZShcclxuICAgICAgICAgIGRlYm91bmNlVGltZSh0aGlzLmRlYm91bmNlTXMoKSksXHJcbiAgICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSxcclxuICAgICAgICApXHJcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLnVwZGF0ZVBvc2l0aW9uKCkpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMudXBkYXRlUG9zaXRpb24oKTtcclxuXHJcbiAgICAodGhpcy5kZXN0cm95UmVmIGFzIGFueSkub25EZXN0cm95Py4oKCkgPT4gcm8uZGlzY29ubmVjdCgpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcmVmZXJlbmNlIGVsZW1lbnQgaXMgY29tcGxldGVseSBvdXRzaWRlIHZpZXdwb3J0LlxyXG4gICAqIEV2ZW4gMXB4IHZpc2libGUgPSBjb25zaWRlcmVkIHZpc2libGUuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBpc1JlZmVyZW5jZUZ1bGx5T3V0KHJlZlJlY3Q6IERPTVJlY3QpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IHZ3ID0gd2luZG93LmlubmVyV2lkdGg7XHJcbiAgICBjb25zdCB2aCA9IHdpbmRvdy5pbm5lckhlaWdodDtcclxuXHJcbiAgICByZXR1cm4gKFxyXG4gICAgICByZWZSZWN0LmJvdHRvbSA8PSAwIHx8IC8vIGFib3ZlIHZpZXdwb3J0XHJcbiAgICAgIHJlZlJlY3QudG9wID49IHZoIHx8IC8vIGJlbG93IHZpZXdwb3J0XHJcbiAgICAgIHJlZlJlY3QucmlnaHQgPD0gMCB8fCAvLyBsZWZ0IG9mIHZpZXdwb3J0XHJcbiAgICAgIHJlZlJlY3QubGVmdCA+PSB2dyAvLyByaWdodCBvZiB2aWV3cG9ydFxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENhbGN1bGF0ZXMgYW5kIGFwcGxpZXMgb3ZlcmxheSBwb3NpdGlvbi5cclxuICAgKi9cclxuICBwcml2YXRlIHVwZGF0ZVBvc2l0aW9uKCk6IHZvaWQge1xyXG4gICAgY29uc3Qgb3ZlcmxheSA9IHRoaXMuZWwubmF0aXZlRWxlbWVudDtcclxuICAgIGNvbnN0IHJlZmVyZW5jZSA9IHRoaXMuZ2V0UmVmZXJlbmNlRWxlbWVudChvdmVybGF5KTtcclxuICAgIGlmICghcmVmZXJlbmNlKSByZXR1cm47XHJcblxyXG4gICAgY29uc3Qgdmlld3BvcnRXID0gd2luZG93LmlubmVyV2lkdGg7XHJcbiAgICBjb25zdCB2aWV3cG9ydEggPSB3aW5kb3cuaW5uZXJIZWlnaHQ7XHJcblxyXG4gICAgY29uc3QgcmVmUmVjdCA9IHJlZmVyZW5jZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuXHJcbiAgICAvLyBPcHRpb25hbGx5IG1hdGNoIHdpZHRoXHJcbiAgICBpZiAodGhpcy5tYXRjaFdpZHRoKCkpIHtcclxuICAgICAgb3ZlcmxheS5zdHlsZS53aWR0aCA9IGAke3JlZlJlY3Qud2lkdGh9cHhgO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IG92ZXJsYXlSZWN0ID0gb3ZlcmxheS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuXHJcbiAgICBjb25zdCBzcGFjZUFib3ZlID0gcmVmUmVjdC50b3A7XHJcbiAgICBjb25zdCBzcGFjZUJlbG93ID0gdmlld3BvcnRIIC0gcmVmUmVjdC5ib3R0b207XHJcblxyXG4gICAgY29uc3Qgb3Blbk9uVG9wID1cclxuICAgICAgb3ZlcmxheVJlY3QuaGVpZ2h0ID4gc3BhY2VCZWxvdyAmJiBzcGFjZUFib3ZlID49IG92ZXJsYXlSZWN0LmhlaWdodDtcclxuXHJcbiAgICAvLyAtLS0gYmFzZSBwb3NpdGlvbmluZyByZWxhdGl2ZSB0byByZWZlcmVuY2UgLS0tXHJcbiAgICBsZXQgdG9wID0gb3Blbk9uVG9wXHJcbiAgICAgID8gcmVmUmVjdC50b3AgLSBvdmVybGF5UmVjdC5oZWlnaHQgLSB0aGlzLm9mZnNldCgpXHJcbiAgICAgIDogcmVmUmVjdC5ib3R0b20gKyB0aGlzLm9mZnNldCgpO1xyXG5cclxuICAgIGxldCBsZWZ0ID0gcmVmUmVjdC5sZWZ0O1xyXG5cclxuICAgIGNvbnN0IGZ1bGx5T3V0ID0gdGhpcy5pc1JlZmVyZW5jZUZ1bGx5T3V0KHJlZlJlY3QpO1xyXG5cclxuICAgIGlmICghZnVsbHlPdXQpIHtcclxuICAgICAgLy8g4pyFIE5PUk1BTCBNT0RFIChyZWZlcmVuY2UgYXQgbGVhc3QgcGFydGlhbGx5IHZpc2libGUpXHJcbiAgICAgIC8vIENsYW1wIHRvIHZpZXdwb3J0XHJcblxyXG4gICAgICB0b3AgPSBNYXRoLm1pbih0b3AsIHZpZXdwb3J0SCAtIG92ZXJsYXlSZWN0LmhlaWdodCAtIDQpO1xyXG4gICAgICBsZWZ0ID0gTWF0aC5taW4obGVmdCwgdmlld3BvcnRXIC0gb3ZlcmxheVJlY3Qud2lkdGggLSA0KTtcclxuICAgIH1cclxuICAgIC8vIGVsc2U6IOKchSBGT0xMT1cgTU9ERSAocmVmZXJlbmNlIGZ1bGx5IG91dCBvZiB2aWV3cG9ydClcclxuICAgIC8vIGRvIE5PVCBjbGFtcCDihpIgbGV0IHBvcHVwIGdvIG9mZnNjcmVlbiBuYXR1cmFsbHlcclxuICAgIC8vIHRvcCAmIGxlZnQgc3RheSByZWxhdGl2ZSB0byByZWZSZWN0XHJcblxyXG4gICAgb3ZlcmxheS5zdHlsZS50b3AgPSBgJHt0b3B9cHhgO1xyXG4gICAgb3ZlcmxheS5zdHlsZS5sZWZ0ID0gYCR7bGVmdH1weGA7XHJcblxyXG4gICAgLy8gT3B0aW9uYWwgaW5uZXIgc2Nyb2xsIGNvbnRhaW5lciBoYW5kbGluZ1xyXG4gICAgaWYgKHRoaXMuc2Nyb2xsYWJsZVNlbGVjdG9yKCkpIHtcclxuICAgICAgY29uc3QgaW5uZXIgPSBvdmVybGF5LnF1ZXJ5U2VsZWN0b3IoXHJcbiAgICAgICAgdGhpcy5zY3JvbGxhYmxlU2VsZWN0b3IoKSEsXHJcbiAgICAgICkgYXMgSFRNTEVsZW1lbnQ7XHJcbiAgICAgIGlmIChpbm5lcikge1xyXG4gICAgICAgIGNvbnN0IG1heFNwYWNlID0gb3Blbk9uVG9wID8gc3BhY2VBYm92ZSA6IHNwYWNlQmVsb3c7XHJcbiAgICAgICAgaW5uZXIuc3R5bGUubWF4SGVpZ2h0ID0gYCR7TWF0aC5taW4obWF4U3BhY2UgLSAxMCwgdmlld3BvcnRIICogMC45KX1weGA7XHJcbiAgICAgICAgaW5uZXIuc3R5bGUub3ZlcmZsb3dZID0gJ2F1dG8nO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gdmlzaWJpbGl0eSBzYWZlIHVwZGF0ZVxyXG4gICAgcXVldWVNaWNyb3Rhc2soKCkgPT4ge1xyXG4gICAgICB0aGlzLnZpc2liaWxpdHkgPSAndmlzaWJsZSc7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlc29sdmVzIHRoZSByZWZlcmVuY2UgZWxlbWVudC5cclxuICAgKi9cclxuICBwcml2YXRlIGdldFJlZmVyZW5jZUVsZW1lbnQob3ZlcmxheTogSFRNTEVsZW1lbnQpOiBIVE1MRWxlbWVudCB8IG51bGwge1xyXG4gICAgY29uc3QgaWQgPSB0aGlzLnJlZmVyZW5jZUVsZW1lbnRJZCgpO1xyXG4gICAgcmV0dXJuIGlkID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpIDogb3ZlcmxheS5wYXJlbnRFbGVtZW50O1xyXG4gIH1cclxufVxyXG4iXX0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './public_api';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctYXV0by1wb3NpdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9uZy1hdXRvLXBvc2l0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxjQUFjLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vcHVibGljX2FwaSc7XG4iXX0=
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export * from './app/ng-auto-position/ng-auto-position.directive';
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljX2FwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wdWJsaWNfYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsbURBQW1ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2FwcC9uZy1hdXRvLXBvc2l0aW9uL25nLWF1dG8tcG9zaXRpb24uZGlyZWN0aXZlJztcclxuIl19
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, DestroyRef, input, HostBinding, Directive } from '@angular/core';
|
|
3
|
+
import { merge, fromEvent } from 'rxjs';
|
|
4
|
+
import { debounceTime } from 'rxjs/operators';
|
|
5
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* AutoPositionElementDirective
|
|
9
|
+
*
|
|
10
|
+
* Automatically positions an overlay element (dropdown / popover)
|
|
11
|
+
* relative to a reference element and keeps it inside the viewport.
|
|
12
|
+
*
|
|
13
|
+
* DESIGN DECISIONS:
|
|
14
|
+
* - Uses `position: fixed` so viewport math is reliable.
|
|
15
|
+
* - Uses getBoundingClientRect() for all measurements.
|
|
16
|
+
* - Avoids DOM depth assumptions (npm-safe).
|
|
17
|
+
* - Uses ResizeObserver to react to size changes.
|
|
18
|
+
*/
|
|
19
|
+
class NgAutoPositionElementDirective {
|
|
20
|
+
/** Native element reference for the overlay */
|
|
21
|
+
el = inject((ElementRef));
|
|
22
|
+
/** Used by Angular to auto-clean RxJS subscriptions */
|
|
23
|
+
destroyRef = inject(DestroyRef);
|
|
24
|
+
/**
|
|
25
|
+
* ID of the reference element.
|
|
26
|
+
* If not provided, parentElement is used.
|
|
27
|
+
*/
|
|
28
|
+
referenceElementId = input(null);
|
|
29
|
+
/** Debounce time for scroll / resize events (ms) */
|
|
30
|
+
debounceMs = input(0);
|
|
31
|
+
/** Gap between reference and overlay (px) */
|
|
32
|
+
offset = input(5);
|
|
33
|
+
/** Match overlay width to reference width */
|
|
34
|
+
matchWidth = input(false);
|
|
35
|
+
/**
|
|
36
|
+
* Optional selector for inner scrollable content
|
|
37
|
+
* whose max-height will be auto-calculated.
|
|
38
|
+
*/
|
|
39
|
+
scrollableSelector = input(null);
|
|
40
|
+
/**
|
|
41
|
+
* Enables or disables automatic repositioning
|
|
42
|
+
* on window scroll and resize.
|
|
43
|
+
*
|
|
44
|
+
* Default: true
|
|
45
|
+
*/
|
|
46
|
+
enableAutoReposition = input(true);
|
|
47
|
+
/**
|
|
48
|
+
* List of element IDs or class names
|
|
49
|
+
* whose scrollbars should be hidden
|
|
50
|
+
* while the popup is visible.
|
|
51
|
+
*
|
|
52
|
+
* Examples:
|
|
53
|
+
* ['body']
|
|
54
|
+
* ['app-layout', '.content-wrapper']
|
|
55
|
+
*/
|
|
56
|
+
hideScrollTargets = input(null);
|
|
57
|
+
/**
|
|
58
|
+
* Hide overlay until positioned to avoid flicker.
|
|
59
|
+
*/
|
|
60
|
+
visibility = 'hidden';
|
|
61
|
+
ngAfterViewInit() {
|
|
62
|
+
const overlay = this.el.nativeElement;
|
|
63
|
+
overlay.style.position = 'fixed';
|
|
64
|
+
// ResizeObserver always useful (content changes)
|
|
65
|
+
const ro = new ResizeObserver(() => this.updatePosition());
|
|
66
|
+
ro.observe(overlay);
|
|
67
|
+
const reference = this.getReferenceElement(overlay);
|
|
68
|
+
if (reference)
|
|
69
|
+
ro.observe(reference);
|
|
70
|
+
// Conditionally listen to scroll + resize
|
|
71
|
+
if (this.enableAutoReposition()) {
|
|
72
|
+
merge(fromEvent(window, 'scroll'), fromEvent(window, 'resize'))
|
|
73
|
+
.pipe(debounceTime(this.debounceMs()), takeUntilDestroyed(this.destroyRef))
|
|
74
|
+
.subscribe(() => this.updatePosition());
|
|
75
|
+
}
|
|
76
|
+
this.updatePosition();
|
|
77
|
+
this.destroyRef.onDestroy?.(() => ro.disconnect());
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Returns true if the reference element is completely outside viewport.
|
|
81
|
+
* Even 1px visible = considered visible.
|
|
82
|
+
*/
|
|
83
|
+
isReferenceFullyOut(refRect) {
|
|
84
|
+
const vw = window.innerWidth;
|
|
85
|
+
const vh = window.innerHeight;
|
|
86
|
+
return (refRect.bottom <= 0 || // above viewport
|
|
87
|
+
refRect.top >= vh || // below viewport
|
|
88
|
+
refRect.right <= 0 || // left of viewport
|
|
89
|
+
refRect.left >= vw // right of viewport
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Calculates and applies overlay position.
|
|
94
|
+
*/
|
|
95
|
+
updatePosition() {
|
|
96
|
+
const overlay = this.el.nativeElement;
|
|
97
|
+
const reference = this.getReferenceElement(overlay);
|
|
98
|
+
if (!reference)
|
|
99
|
+
return;
|
|
100
|
+
const viewportW = window.innerWidth;
|
|
101
|
+
const viewportH = window.innerHeight;
|
|
102
|
+
const refRect = reference.getBoundingClientRect();
|
|
103
|
+
// Optionally match width
|
|
104
|
+
if (this.matchWidth()) {
|
|
105
|
+
overlay.style.width = `${refRect.width}px`;
|
|
106
|
+
}
|
|
107
|
+
const overlayRect = overlay.getBoundingClientRect();
|
|
108
|
+
const spaceAbove = refRect.top;
|
|
109
|
+
const spaceBelow = viewportH - refRect.bottom;
|
|
110
|
+
const openOnTop = overlayRect.height > spaceBelow && spaceAbove >= overlayRect.height;
|
|
111
|
+
// --- base positioning relative to reference ---
|
|
112
|
+
let top = openOnTop
|
|
113
|
+
? refRect.top - overlayRect.height - this.offset()
|
|
114
|
+
: refRect.bottom + this.offset();
|
|
115
|
+
let left = refRect.left;
|
|
116
|
+
const fullyOut = this.isReferenceFullyOut(refRect);
|
|
117
|
+
if (!fullyOut) {
|
|
118
|
+
// ✅ NORMAL MODE (reference at least partially visible)
|
|
119
|
+
// Clamp to viewport
|
|
120
|
+
top = Math.min(top, viewportH - overlayRect.height - 4);
|
|
121
|
+
left = Math.min(left, viewportW - overlayRect.width - 4);
|
|
122
|
+
}
|
|
123
|
+
// else: ✅ FOLLOW MODE (reference fully out of viewport)
|
|
124
|
+
// do NOT clamp → let popup go offscreen naturally
|
|
125
|
+
// top & left stay relative to refRect
|
|
126
|
+
overlay.style.top = `${top}px`;
|
|
127
|
+
overlay.style.left = `${left}px`;
|
|
128
|
+
// Optional inner scroll container handling
|
|
129
|
+
if (this.scrollableSelector()) {
|
|
130
|
+
const inner = overlay.querySelector(this.scrollableSelector());
|
|
131
|
+
if (inner) {
|
|
132
|
+
const maxSpace = openOnTop ? spaceAbove : spaceBelow;
|
|
133
|
+
inner.style.maxHeight = `${Math.min(maxSpace - 10, viewportH * 0.9)}px`;
|
|
134
|
+
inner.style.overflowY = 'auto';
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// visibility safe update
|
|
138
|
+
queueMicrotask(() => {
|
|
139
|
+
this.visibility = 'visible';
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Resolves the reference element.
|
|
144
|
+
*/
|
|
145
|
+
getReferenceElement(overlay) {
|
|
146
|
+
const id = this.referenceElementId();
|
|
147
|
+
return id ? document.getElementById(id) : overlay.parentElement;
|
|
148
|
+
}
|
|
149
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgAutoPositionElementDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
150
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "17.3.12", type: NgAutoPositionElementDirective, isStandalone: true, selector: "[ngAutoPosition]", inputs: { referenceElementId: { classPropertyName: "referenceElementId", publicName: "referenceElementId", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "offset", isSignal: true, isRequired: false, transformFunction: null }, matchWidth: { classPropertyName: "matchWidth", publicName: "matchWidth", isSignal: true, isRequired: false, transformFunction: null }, scrollableSelector: { classPropertyName: "scrollableSelector", publicName: "scrollableSelector", isSignal: true, isRequired: false, transformFunction: null }, enableAutoReposition: { classPropertyName: "enableAutoReposition", publicName: "enableAutoReposition", isSignal: true, isRequired: false, transformFunction: null }, hideScrollTargets: { classPropertyName: "hideScrollTargets", publicName: "hideScrollTargets", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.visibility": "this.visibility" } }, ngImport: i0 });
|
|
151
|
+
}
|
|
152
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NgAutoPositionElementDirective, decorators: [{
|
|
153
|
+
type: Directive,
|
|
154
|
+
args: [{
|
|
155
|
+
selector: '[ngAutoPosition]',
|
|
156
|
+
standalone: true,
|
|
157
|
+
}]
|
|
158
|
+
}], propDecorators: { visibility: [{
|
|
159
|
+
type: HostBinding,
|
|
160
|
+
args: ['style.visibility']
|
|
161
|
+
}] } });
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Generated bundle index. Do not edit.
|
|
165
|
+
*/
|
|
166
|
+
|
|
167
|
+
export { NgAutoPositionElementDirective };
|
|
168
|
+
//# sourceMappingURL=ng-auto-position.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ng-auto-position.mjs","sources":["../../src/app/ng-auto-position/ng-auto-position.directive.ts","../../src/ng-auto-position.ts"],"sourcesContent":["import {\r\n AfterViewInit,\r\n DestroyRef,\r\n Directive,\r\n ElementRef,\r\n HostBinding,\r\n inject,\r\n input,\r\n} from '@angular/core';\r\nimport { fromEvent, merge } from 'rxjs';\r\nimport { debounceTime } from 'rxjs/operators';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\n\r\n/**\r\n * AutoPositionElementDirective\r\n *\r\n * Automatically positions an overlay element (dropdown / popover)\r\n * relative to a reference element and keeps it inside the viewport.\r\n *\r\n * DESIGN DECISIONS:\r\n * - Uses `position: fixed` so viewport math is reliable.\r\n * - Uses getBoundingClientRect() for all measurements.\r\n * - Avoids DOM depth assumptions (npm-safe).\r\n * - Uses ResizeObserver to react to size changes.\r\n */\r\n@Directive({\r\n selector: '[ngAutoPosition]',\r\n standalone: true,\r\n})\r\nexport class NgAutoPositionElementDirective implements AfterViewInit {\r\n /** Native element reference for the overlay */\r\n private readonly el = inject(ElementRef<HTMLElement>);\r\n\r\n /** Used by Angular to auto-clean RxJS subscriptions */\r\n private readonly destroyRef = inject(DestroyRef);\r\n\r\n /**\r\n * ID of the reference element.\r\n * If not provided, parentElement is used.\r\n */\r\n referenceElementId = input<string | null>(null);\r\n\r\n /** Debounce time for scroll / resize events (ms) */\r\n debounceMs = input<number>(0);\r\n\r\n /** Gap between reference and overlay (px) */\r\n offset = input<number>(5);\r\n\r\n /** Match overlay width to reference width */\r\n matchWidth = input<boolean>(false);\r\n\r\n /**\r\n * Optional selector for inner scrollable content\r\n * whose max-height will be auto-calculated.\r\n */\r\n scrollableSelector = input<string | null>(null);\r\n\r\n /**\r\n * Enables or disables automatic repositioning\r\n * on window scroll and resize.\r\n *\r\n * Default: true\r\n */\r\n enableAutoReposition = input<boolean>(true);\r\n\r\n /**\r\n * List of element IDs or class names\r\n * whose scrollbars should be hidden\r\n * while the popup is visible.\r\n *\r\n * Examples:\r\n * ['body']\r\n * ['app-layout', '.content-wrapper']\r\n */\r\n hideScrollTargets = input<string[] | null>(null);\r\n\r\n /**\r\n * Hide overlay until positioned to avoid flicker.\r\n */\r\n @HostBinding('style.visibility')\r\n visibility: 'hidden' | 'visible' = 'hidden';\r\n\r\n ngAfterViewInit(): void {\r\n const overlay = this.el.nativeElement;\r\n overlay.style.position = 'fixed';\r\n\r\n // ResizeObserver always useful (content changes)\r\n const ro = new ResizeObserver(() => this.updatePosition());\r\n ro.observe(overlay);\r\n\r\n const reference = this.getReferenceElement(overlay);\r\n if (reference) ro.observe(reference);\r\n\r\n // Conditionally listen to scroll + resize\r\n if (this.enableAutoReposition()) {\r\n merge(fromEvent(window, 'scroll'), fromEvent(window, 'resize'))\r\n .pipe(\r\n debounceTime(this.debounceMs()),\r\n takeUntilDestroyed(this.destroyRef),\r\n )\r\n .subscribe(() => this.updatePosition());\r\n }\r\n\r\n this.updatePosition();\r\n\r\n (this.destroyRef as any).onDestroy?.(() => ro.disconnect());\r\n }\r\n\r\n /**\r\n * Returns true if the reference element is completely outside viewport.\r\n * Even 1px visible = considered visible.\r\n */\r\n private isReferenceFullyOut(refRect: DOMRect): boolean {\r\n const vw = window.innerWidth;\r\n const vh = window.innerHeight;\r\n\r\n return (\r\n refRect.bottom <= 0 || // above viewport\r\n refRect.top >= vh || // below viewport\r\n refRect.right <= 0 || // left of viewport\r\n refRect.left >= vw // right of viewport\r\n );\r\n }\r\n\r\n /**\r\n * Calculates and applies overlay position.\r\n */\r\n private updatePosition(): void {\r\n const overlay = this.el.nativeElement;\r\n const reference = this.getReferenceElement(overlay);\r\n if (!reference) return;\r\n\r\n const viewportW = window.innerWidth;\r\n const viewportH = window.innerHeight;\r\n\r\n const refRect = reference.getBoundingClientRect();\r\n\r\n // Optionally match width\r\n if (this.matchWidth()) {\r\n overlay.style.width = `${refRect.width}px`;\r\n }\r\n\r\n const overlayRect = overlay.getBoundingClientRect();\r\n\r\n const spaceAbove = refRect.top;\r\n const spaceBelow = viewportH - refRect.bottom;\r\n\r\n const openOnTop =\r\n overlayRect.height > spaceBelow && spaceAbove >= overlayRect.height;\r\n\r\n // --- base positioning relative to reference ---\r\n let top = openOnTop\r\n ? refRect.top - overlayRect.height - this.offset()\r\n : refRect.bottom + this.offset();\r\n\r\n let left = refRect.left;\r\n\r\n const fullyOut = this.isReferenceFullyOut(refRect);\r\n\r\n if (!fullyOut) {\r\n // ✅ NORMAL MODE (reference at least partially visible)\r\n // Clamp to viewport\r\n\r\n top = Math.min(top, viewportH - overlayRect.height - 4);\r\n left = Math.min(left, viewportW - overlayRect.width - 4);\r\n }\r\n // else: ✅ FOLLOW MODE (reference fully out of viewport)\r\n // do NOT clamp → let popup go offscreen naturally\r\n // top & left stay relative to refRect\r\n\r\n overlay.style.top = `${top}px`;\r\n overlay.style.left = `${left}px`;\r\n\r\n // Optional inner scroll container handling\r\n if (this.scrollableSelector()) {\r\n const inner = overlay.querySelector(\r\n this.scrollableSelector()!,\r\n ) as HTMLElement;\r\n if (inner) {\r\n const maxSpace = openOnTop ? spaceAbove : spaceBelow;\r\n inner.style.maxHeight = `${Math.min(maxSpace - 10, viewportH * 0.9)}px`;\r\n inner.style.overflowY = 'auto';\r\n }\r\n }\r\n\r\n // visibility safe update\r\n queueMicrotask(() => {\r\n this.visibility = 'visible';\r\n });\r\n }\r\n\r\n /**\r\n * Resolves the reference element.\r\n */\r\n private getReferenceElement(overlay: HTMLElement): HTMLElement | null {\r\n const id = this.referenceElementId();\r\n return id ? document.getElementById(id) : overlay.parentElement;\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ng-auto-position",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Angular directive for auto positioning dropdowns and popovers",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@angular/animations": "^17.3.0",
|
|
7
|
+
"@angular/common": "^17.3.0",
|
|
8
|
+
"@angular/compiler": "^17.3.0",
|
|
9
|
+
"@angular/core": "^17.3.0",
|
|
10
|
+
"@angular/forms": "^17.3.0",
|
|
11
|
+
"@angular/platform-browser": "^17.3.0",
|
|
12
|
+
"@angular/platform-browser-dynamic": "^17.3.0",
|
|
13
|
+
"@angular/router": "^17.3.0",
|
|
14
|
+
"del-cli": "^5.1.0",
|
|
15
|
+
"rxjs": "~7.8.0",
|
|
16
|
+
"tslib": "^2.3.0",
|
|
17
|
+
"zone.js": "~0.14.3"
|
|
18
|
+
},
|
|
19
|
+
"module": "fesm2022/ng-auto-position.mjs",
|
|
20
|
+
"typings": "index.d.ts",
|
|
21
|
+
"exports": {
|
|
22
|
+
"./package.json": {
|
|
23
|
+
"default": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./index.d.ts",
|
|
27
|
+
"esm2022": "./esm2022/ng-auto-position.mjs",
|
|
28
|
+
"esm": "./esm2022/ng-auto-position.mjs",
|
|
29
|
+
"default": "./fesm2022/ng-auto-position.mjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"sideEffects": false
|
|
33
|
+
}
|
package/public_api.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './app/ng-auto-position/ng-auto-position.directive';
|