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 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
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="ng-auto-position" />
5
+ export * from './public_api';
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
+ }
@@ -0,0 +1 @@
1
+ export * from './app/ng-auto-position/ng-auto-position.directive';