@uniprank/ngx-scrollspy 1.0.9 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +102 -81
  2. package/fesm2022/uniprank-ngx-scrollspy.mjs +389 -0
  3. package/fesm2022/uniprank-ngx-scrollspy.mjs.map +1 -0
  4. package/index.d.ts +6 -0
  5. package/lib/ngx-scrollspy.module.d.ts +24 -1
  6. package/lib/ngx-scrollspy.module.d.ts.map +1 -0
  7. package/lib/scroll-direction.enum.d.ts +1 -0
  8. package/lib/scroll-direction.enum.d.ts.map +1 -0
  9. package/lib/scroll-element.directive.d.ts +12 -9
  10. package/lib/scroll-element.directive.d.ts.map +1 -0
  11. package/lib/scroll-element.interface.d.ts +1 -0
  12. package/lib/scroll-element.interface.d.ts.map +1 -0
  13. package/lib/scroll-item.directive.d.ts +12 -12
  14. package/lib/scroll-item.directive.d.ts.map +1 -0
  15. package/lib/scroll-object.interface.d.ts +1 -0
  16. package/lib/scroll-object.interface.d.ts.map +1 -0
  17. package/lib/scroll-spy.directive.d.ts +11 -10
  18. package/lib/scroll-spy.directive.d.ts.map +1 -0
  19. package/lib/scroll-spy.service.d.ts +13 -10
  20. package/lib/scroll-spy.service.d.ts.map +1 -0
  21. package/package.json +22 -15
  22. package/public-api.d.ts +3 -1
  23. package/public-api.d.ts.map +1 -0
  24. package/uniprank-ngx-scrollspy.d.ts.map +1 -0
  25. package/CHANGELOG.md +0 -26
  26. package/bundles/uniprank-ngx-scrollspy.umd.js +0 -649
  27. package/bundles/uniprank-ngx-scrollspy.umd.js.map +0 -1
  28. package/bundles/uniprank-ngx-scrollspy.umd.min.js +0 -16
  29. package/bundles/uniprank-ngx-scrollspy.umd.min.js.map +0 -1
  30. package/esm2015/lib/ngx-scrollspy.module.js +0 -28
  31. package/esm2015/lib/scroll-direction.enum.js +0 -6
  32. package/esm2015/lib/scroll-element.directive.js +0 -63
  33. package/esm2015/lib/scroll-element.interface.js +0 -1
  34. package/esm2015/lib/scroll-item.directive.js +0 -61
  35. package/esm2015/lib/scroll-object.interface.js +0 -1
  36. package/esm2015/lib/scroll-spy.directive.js +0 -60
  37. package/esm2015/lib/scroll-spy.service.js +0 -210
  38. package/esm2015/public-api.js +0 -14
  39. package/esm2015/uniprank-ngx-scrollspy.js +0 -6
  40. package/esm5/lib/ngx-scrollspy.module.js +0 -33
  41. package/esm5/lib/scroll-direction.enum.js +0 -6
  42. package/esm5/lib/scroll-element.directive.js +0 -65
  43. package/esm5/lib/scroll-element.interface.js +0 -1
  44. package/esm5/lib/scroll-item.directive.js +0 -63
  45. package/esm5/lib/scroll-object.interface.js +0 -1
  46. package/esm5/lib/scroll-spy.directive.js +0 -62
  47. package/esm5/lib/scroll-spy.service.js +0 -219
  48. package/esm5/public-api.js +0 -14
  49. package/esm5/uniprank-ngx-scrollspy.js +0 -6
  50. package/fesm2015/uniprank-ngx-scrollspy.js +0 -415
  51. package/fesm2015/uniprank-ngx-scrollspy.js.map +0 -1
  52. package/fesm5/uniprank-ngx-scrollspy.js +0 -435
  53. package/fesm5/uniprank-ngx-scrollspy.js.map +0 -1
  54. package/uniprank-ngx-scrollspy.d.ts +0 -5
  55. package/uniprank-ngx-scrollspy.metadata.json +0 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
- [![travis build](https://img.shields.io/travis/uniprank/ngx-scrollspy?label=Travis%3Abuild&style=flat-square)](https://travis-ci.org/uniprank/ngx-scrollspy)
1
+ [![CI](https://github.com/uniprank/ngx-scrollspy/actions/workflows/ci.yml/badge.svg)](https://github.com/uniprank/ngx-scrollspy/actions/workflows/ci.yml)
2
2
 
3
3
  You can use this angular service to spy scroll events from `window` or any other scrollable element.
4
4
 
5
- This library implements an service to collect observables from scroll spy directives. It can be used to create you own components or if you prefer use one of the following directives.
5
+ This library implements a service to collect observables from scroll spy directives. It can be used to create your own components or if you prefer use one of the following directives.
6
6
 
7
7
  See Examples here [Example](https://uniprank.github.io/ngx-scrollspy/test-cases)
8
8
 
@@ -14,116 +14,137 @@ First you need to install the npm module:
14
14
  npm install @uniprank/ngx-scrollspy --save
15
15
  ```
16
16
 
17
- If you use SystemJS to load your files, you might have to update your config with this if you don't use `defaultJSExtensions: true`:
17
+ ## Setup (Standalone API)
18
18
 
19
- ```js
20
- System.config({
21
- packages: {
22
- '@uniprank/ngx-scrollspy': { defaultExtension: 'js' }
23
- }
24
- });
19
+ Use `provideScrollSpy()` in your application config to set up the service:
20
+
21
+ ```typescript
22
+ // app.config.ts
23
+ import { ApplicationConfig } from '@angular/core';
24
+ import { provideScrollSpy } from '@uniprank/ngx-scrollspy';
25
+
26
+ export const appConfig: ApplicationConfig = {
27
+ providers: [
28
+ provideScrollSpy({ lookAhead: true })
29
+ ]
30
+ };
25
31
  ```
26
32
 
27
- Finally, you can use ngx-scrollspy in your Angular project (NOT AngularJS).
28
- It is recommended to instantiate `ScrollSpyService` in the bootstrap of your application and to never add it to the "providers" property of your components, this way you will keep it as a singleton.
29
- If you add it to the "providers" property of a component it will instantiate a new instance of the service that won't be initialized.
33
+ ```typescript
34
+ // main.ts
35
+ import { bootstrapApplication } from '@angular/platform-browser';
36
+ import { AppComponent } from './app/app.component';
37
+ import { appConfig } from './app/app.config';
30
38
 
31
- ```js
32
- import { NgModule } from '@angular/core';
33
- import { BrowserModule } from '@angular/platform-browser';
39
+ bootstrapApplication(AppComponent, appConfig);
40
+ ```
41
+
42
+ Then import the standalone directives directly in your components:
34
43
 
35
- import { ScrollSpyModule } from '@uniprank/ngx-scrollspy';
44
+ ```typescript
45
+ import { Component } from '@angular/core';
46
+ import { ScrollSpyDirective, ScrollItemDirective } from '@uniprank/ngx-scrollspy';
36
47
 
37
- @NgModule({
38
- imports: [BrowserModule, ScrollSpyModule.forRoot()],
39
- declarations: [AppComponent],
40
- bootstrap: [AppComponent]
48
+ @Component({
49
+ selector: 'app-example',
50
+ standalone: true,
51
+ imports: [ScrollSpyDirective, ScrollItemDirective],
52
+ template: `
53
+ <li uniScrollItem="section1">Section 1</li>
54
+ <section uniScrollSpy="section1">Content</section>
55
+ `
41
56
  })
42
- export class AppModule {}
57
+ export class ExampleComponent {}
43
58
  ```
44
59
 
60
+ ### Available Directives
61
+
62
+ | Directive | Selector | Description |
63
+ |-----------|----------|-------------|
64
+ | `ScrollSpyDirective` | `[uniScrollSpy]` | Marks a content section to be tracked by the scroll spy |
65
+ | `ScrollItemDirective` | `[uniScrollItem]` | Marks a navigation item that mirrors the active state |
66
+ | `ScrollElementDirective` | `[uniScrollElement]` | Wraps a custom scrollable container (non-window) |
67
+
45
68
  ## Using
46
69
 
47
70
  #### Spy window scroll
48
71
 
49
- Use `ScrollSpyDirective` to spy on window as default or set also element to spy on a other scroll able element.
72
+ Use `ScrollSpyDirective` to spy on window as default or set `scrollElement` to spy on another scrollable element.
50
73
 
51
- ```js
52
- import { NgModule, Component, Injectable, AfterViewInit } from '@angular/core';
53
- import { BrowserModule } from '@angular/platform-browser';
74
+ ```typescript
75
+ import { Component } from '@angular/core';
76
+ import { ScrollSpyDirective, ScrollItemDirective, ScrollSpyService } from '@uniprank/ngx-scrollspy';
54
77
 
55
- import { ScrollSpyModule, ScrollSpyService, ScrollObjectInterface } from '@uniprank/ngx-scrollspy';
56
-
57
- @Injectable()
58
78
  @Component({
59
- selector: 'app',
60
- template: `<div uniScrollSpy="section-abc"></div>`
79
+ selector: 'app-example',
80
+ standalone: true,
81
+ imports: [ScrollSpyDirective, ScrollItemDirective],
82
+ template: `<div uniScrollSpy="section-abc"></div>`
61
83
  })
62
- export class AppComponent implements AfterViewInit {
63
- constructor(private _scrollSpyService: ScrollSpyService) {}
64
-
65
- ngAfterViewInit() {
66
- this._scrollSpyService.getObservable('window').subscribe((element: ScrollObjectInterface) => {
67
- console.log('ScrollSpy::window: ', element);
68
- });
69
- }
70
- }
84
+ export class ExampleComponent implements AfterViewInit {
85
+ constructor(private _scrollSpyService: ScrollSpyService) {}
71
86
 
72
- @NgModule({
73
- imports: [
74
- BrowserModule,
75
- ScrollSpyModule.forRoot()
76
- ],
77
- declarations: [
78
- AppComponent
79
- ],
80
- bootstrap: [ AppComponent ]
81
- })
87
+ ngAfterViewInit() {
88
+ this._scrollSpyService.observe('window').subscribe((element) => {
89
+ console.log('ScrollSpy::window: ', element);
90
+ });
91
+ }
92
+ }
82
93
  ```
83
94
 
84
95
  #### Spy any element scroll
85
96
 
86
- Use `ScrollSpyElementDirective` to spy on any element. You must give an unique id to each instance.
87
- This unique id is called elementID and you need this elementID to connect your `ScrollSpyItemDirective` or your `ScrollSpyDirective`.
97
+ Use `ScrollElementDirective` to spy on any element. You must give a unique id to each instance.
98
+ This unique id is called elementID and you need this elementID to connect your `ScrollItemDirective` or your `ScrollSpyDirective`.
88
99
 
89
- ```js
90
- import { NgModule, Component, Injectable, AfterViewInit } from '@angular/core';
91
- import { ScrollSpyModule, ScrollSpyService, ScrollObjectInterface } from '@uniprank/ngx-scrollspy';
100
+ ```typescript
101
+ import { Component, AfterViewInit } from '@angular/core';
102
+ import {
103
+ ScrollSpyDirective,
104
+ ScrollItemDirective,
105
+ ScrollElementDirective,
106
+ ScrollSpyService,
107
+ ScrollObjectInterface
108
+ } from '@uniprank/ngx-scrollspy';
92
109
 
93
- @Injectable()
94
110
  @Component({
95
- selector: 'yourComponent',
111
+ selector: 'app-example',
112
+ standalone: true,
113
+ imports: [ScrollSpyDirective, ScrollItemDirective, ScrollElementDirective],
96
114
  template: `
97
- <div uniScrollSpyItem="part2" scrollElement="test">Get class active if part2 is in focus.</div>
98
- <div uniScrollSpyElement="test" style="max-height: 100px; overflow: auto;">
99
- <div uniScrollSpy="part1" style="height: 500px;"></div>
100
- <div uniScrollSpy="part2" style="height: 500px;"></div>
101
- </div>`
115
+ <div uniScrollItem="part2" scrollElement="test">Get class active if part2 is in focus.</div>
116
+ <div uniScrollElement="test" style="max-height: 100px; overflow: auto;">
117
+ <div uniScrollSpy="part1" style="height: 500px;"></div>
118
+ <div uniScrollSpy="part2" style="height: 500px;"></div>
119
+ </div>
120
+ `
102
121
  })
103
- export class YourComponent implements AfterViewInit {
104
-
105
- constructor(private _scrollSpyService: ScrollSpyService) {}
122
+ export class ExampleComponent implements AfterViewInit {
123
+ constructor(private _scrollSpyService: ScrollSpyService) {}
106
124
 
107
- ngAfterViewInit() {
108
- this._scrollSpyService.getObservable('test').subscribe((element: ScrollObjectInterface) => {
109
- console.log('ScrollSpy::test: ', element);
110
- });
111
- }
125
+ ngAfterViewInit() {
126
+ this._scrollSpyService.observe('test').subscribe((element: ScrollObjectInterface) => {
127
+ console.log('ScrollSpy::test: ', element);
128
+ });
129
+ }
112
130
  }
113
-
114
- @NgModule({
115
- imports: [
116
- ScrollSpyModule
117
- ],
118
- declarations: [
119
- AppComponent
120
- ],
121
- providers: [ ]
122
- })
123
- export class YourModule { }
124
131
  ```
125
132
 
126
- Because `ScrollSpyService` is a singleton, you can get any ScrollSpy observable from anywhere withing your application.
133
+ Because `ScrollSpyService` is a singleton, you can get any ScrollSpy observable from anywhere within your application.
134
+
135
+ ## Parameters
136
+
137
+ You can pass optional parameters to `provideScrollSpy()`:
138
+
139
+ | Parameter | Value | Description |
140
+ |-----------|-------|-------------|
141
+ | `lookAhead` | boolean | Set the first item active even if it's not already in the viewport |
142
+ | `activateOnlySetItems` | boolean | Only activate items when fully within the viewport |
143
+ | `attributeType` | `'id'` \| `'data-id'` | Which HTML attribute to set on spy elements (default: `'id'`) |
144
+
145
+ ```typescript
146
+ provideScrollSpy({ lookAhead: true })
147
+ ```
127
148
 
128
149
  # TODO:
129
150
 
@@ -0,0 +1,389 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, inject, ElementRef, Injectable, input, signal, DestroyRef, Directive, contentChildren, output, makeEnvironmentProviders, NgModule } from '@angular/core';
3
+ import { DOCUMENT } from '@angular/common';
4
+ import { Subject, fromEvent, BehaviorSubject } from 'rxjs';
5
+ import { auditTime, takeUntil } from 'rxjs/operators';
6
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
7
+
8
+ var ScrollDirectionEnum;
9
+ (function (ScrollDirectionEnum) {
10
+ ScrollDirectionEnum["vertical"] = "vertical";
11
+ ScrollDirectionEnum["horizontal"] = "horizontal";
12
+ })(ScrollDirectionEnum || (ScrollDirectionEnum = {}));
13
+
14
+ const defaultElementId = 'window';
15
+ const SPY_CONFIG = new InjectionToken('SPY_CONFIG');
16
+ class ScrollSpyService {
17
+ constructor() {
18
+ this._doc = inject(DOCUMENT);
19
+ this._config = inject(SPY_CONFIG, { optional: true });
20
+ this._scrollItems = {};
21
+ this._scrollElements = {};
22
+ this._$scrollElementListener = {};
23
+ this._scrollElementListener = {};
24
+ this._onStopListening = new Subject();
25
+ this._window = this._doc.defaultView;
26
+ this._initScrollElementListener(defaultElementId, this._generateScrollElement(defaultElementId, new ElementRef(this._doc.documentElement || this._doc.body), ScrollDirectionEnum.vertical));
27
+ if (this._window) {
28
+ fromEvent(this._window, 'resize')
29
+ .pipe(auditTime(300), takeUntil(this._onStopListening))
30
+ .subscribe(() => this._windowScroll());
31
+ fromEvent(this._window, 'scroll')
32
+ .pipe(auditTime(10), takeUntil(this._onStopListening))
33
+ .subscribe(() => this._windowScroll());
34
+ }
35
+ this._windowScroll();
36
+ if (this._config != null) {
37
+ this._lookAhead = this._config.lookAhead ?? false;
38
+ this._activateOnlySetItems = this._config.activateOnlySetItems ?? false;
39
+ this.attributeType = this._config.attributeType ?? 'id';
40
+ }
41
+ else {
42
+ this._lookAhead = false;
43
+ this._activateOnlySetItems = false;
44
+ this.attributeType = 'id';
45
+ }
46
+ }
47
+ _initScrollElementListener(scrollElementId, scrollElement) {
48
+ this._scrollElements[scrollElementId] = scrollElement;
49
+ this._scrollElementListener[scrollElementId] = null;
50
+ this._$scrollElementListener[scrollElementId] = new BehaviorSubject(null);
51
+ }
52
+ _windowScroll() {
53
+ this.updateScrollElement(defaultElementId);
54
+ }
55
+ _generateScrollElement(scrollElementId, elementRef, direction, offset = 0) {
56
+ return {
57
+ id: scrollElementId,
58
+ elementRef,
59
+ direction,
60
+ offset
61
+ };
62
+ }
63
+ setOffset(scrollElementId, offset) {
64
+ this._checkScrollElementExists(scrollElementId);
65
+ this._scrollElements[scrollElementId].offset = offset;
66
+ }
67
+ setScrollElement(scrollElementId, elementRef, direction, offset = 0) {
68
+ const existing = this._scrollElements[scrollElementId];
69
+ if (existing != null && existing.elementRef.nativeElement.isConnected) {
70
+ throw new Error(`ScrollSpyService: The scroll element with the id [${scrollElementId}] already exists in the DOM.`);
71
+ }
72
+ this._initScrollElementListener(scrollElementId, this._generateScrollElement(scrollElementId, elementRef, direction, offset));
73
+ }
74
+ setItem(itemId, elementRef, scrollElementId = defaultElementId) {
75
+ const existing = this._scrollItems[itemId];
76
+ if (existing != null && existing.nativeElement.isConnected) {
77
+ throw new Error(`ScrollSpyService: The scroll item with the id [${itemId}] already exists in the DOM.`);
78
+ }
79
+ this._scrollItems[itemId] = this._generateScrollObject(itemId, elementRef, scrollElementId);
80
+ this._setDefaultItem(itemId, scrollElementId);
81
+ }
82
+ _generateScrollObject(id, elementRef, scrollElementId) {
83
+ return {
84
+ id,
85
+ scrollElementId,
86
+ elementRef,
87
+ nativeElement: elementRef.nativeElement
88
+ };
89
+ }
90
+ _setDefaultItem(itemId, scrollElementId) {
91
+ if (this._lookAhead) {
92
+ return;
93
+ }
94
+ const _value = this._scrollElementListener[scrollElementId];
95
+ if (_value == null) {
96
+ this._setScrollElementListener(scrollElementId, this._scrollItems[itemId]);
97
+ }
98
+ }
99
+ _setScrollElementListener(scrollElementId, scrollObject) {
100
+ this._scrollElementListener[scrollElementId] = scrollObject;
101
+ setTimeout(() => this._$scrollElementListener[scrollElementId].next(scrollObject));
102
+ }
103
+ changeScrollElement(itemId, oldElementId, newElementId, override = false) {
104
+ this._checkScrollElementExists(oldElementId);
105
+ this._checkScrollElementExists(newElementId);
106
+ this._checkItemExists(itemId);
107
+ const _scrollItem = this._scrollItems[itemId];
108
+ if ((_scrollItem.scrollElementId !== defaultElementId && override) || _scrollItem.scrollElementId === defaultElementId) {
109
+ this._scrollItems[itemId].scrollElementId = newElementId;
110
+ }
111
+ this._setDefaultItem(itemId, newElementId);
112
+ const _oldElements = this._getElementItems(oldElementId);
113
+ if (_oldElements.length > 0) {
114
+ this._setDefaultItem(_oldElements[0].id, oldElementId);
115
+ }
116
+ }
117
+ _getElementItems(scrollElementId) {
118
+ const _items = [];
119
+ for (const key in this._scrollItems) {
120
+ if (Object.prototype.hasOwnProperty.call(this._scrollItems, key)) {
121
+ const value = this._scrollItems[key];
122
+ if (value.scrollElementId === scrollElementId) {
123
+ _items.push(value);
124
+ }
125
+ }
126
+ }
127
+ return _items;
128
+ }
129
+ _checkItemExists(itemId) {
130
+ if (this._scrollItems[itemId] == null) {
131
+ throw new Error(`ScrollSpyService: The scroll item with the id [${itemId}] doesn't exist.`);
132
+ }
133
+ }
134
+ observe(scrollElementId = defaultElementId) {
135
+ this._checkScrollElementExists(scrollElementId);
136
+ return this._$scrollElementListener[scrollElementId].asObservable();
137
+ }
138
+ _checkScrollElementExists(scrollElementId) {
139
+ if (this._scrollElements[scrollElementId] == null) {
140
+ throw new Error(`ScrollSpyService: The scroll element with the id [${scrollElementId}] doesn't exist.`);
141
+ }
142
+ }
143
+ updateScrollElement(scrollElementId) {
144
+ this._checkScrollElementExists(scrollElementId);
145
+ const _element = this._scrollElements[scrollElementId];
146
+ const _elementItems = this._getElementItems(scrollElementId);
147
+ const _nextActiveItem = this._getActiveItem(_element, _elementItems);
148
+ const _currentActiveItem = this._scrollElementListener[scrollElementId];
149
+ if (_currentActiveItem == null) {
150
+ if (_nextActiveItem != null) {
151
+ this._setScrollElementListener(scrollElementId, _nextActiveItem);
152
+ }
153
+ }
154
+ else if (_nextActiveItem != null) {
155
+ if (_currentActiveItem.id !== _nextActiveItem.id) {
156
+ this._setScrollElementListener(scrollElementId, _nextActiveItem);
157
+ }
158
+ }
159
+ else if (_nextActiveItem == null && this._lookAhead) {
160
+ this._setScrollElementListener(scrollElementId, null);
161
+ }
162
+ }
163
+ _getActiveItem(scrollElement, listOfElements) {
164
+ const _direction = scrollElement.direction;
165
+ let _scrollObject = null;
166
+ const nativeElement = scrollElement.elementRef.nativeElement;
167
+ listOfElements.forEach((_element) => {
168
+ let _active = false;
169
+ switch (_direction) {
170
+ case ScrollDirectionEnum.horizontal: {
171
+ const _scrollLeft = scrollElement.id.toLowerCase() === 'window' ? (this._window?.pageXOffset ?? 0) : nativeElement.scrollLeft;
172
+ _active = _element.nativeElement.offsetLeft <= _scrollLeft + scrollElement.offset;
173
+ break;
174
+ }
175
+ default: {
176
+ const _scrollTop = scrollElement.id.toLowerCase() === 'window' ? (this._window?.scrollY ?? 0) : nativeElement.scrollTop;
177
+ if (this._activateOnlySetItems) {
178
+ _active =
179
+ _element.nativeElement.offsetTop < _scrollTop + scrollElement.offset &&
180
+ _element.nativeElement.offsetTop + _element.nativeElement.offsetHeight > _scrollTop + scrollElement.offset;
181
+ }
182
+ else {
183
+ _active = _element.nativeElement.offsetTop <= _scrollTop + scrollElement.offset;
184
+ }
185
+ }
186
+ }
187
+ if (_active) {
188
+ _scrollObject = _element;
189
+ }
190
+ });
191
+ return _scrollObject;
192
+ }
193
+ deleteScrollElement(scrollElementId) {
194
+ if (scrollElementId === 'window') {
195
+ this._setScrollElementListener(scrollElementId, null);
196
+ }
197
+ else {
198
+ this._checkScrollElementExists(scrollElementId);
199
+ delete this._scrollElements[scrollElementId];
200
+ delete this._$scrollElementListener[scrollElementId];
201
+ delete this._scrollElementListener[scrollElementId];
202
+ }
203
+ }
204
+ deleteItem(itemId) {
205
+ if (this._scrollItems[itemId] != null) {
206
+ delete this._scrollItems[itemId];
207
+ }
208
+ }
209
+ destroy() {
210
+ this._onStopListening.next();
211
+ this._onStopListening.complete();
212
+ }
213
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollSpyService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
214
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollSpyService, providedIn: 'root' }); }
215
+ }
216
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollSpyService, decorators: [{
217
+ type: Injectable,
218
+ args: [{ providedIn: 'root' }]
219
+ }], ctorParameters: () => [] });
220
+
221
+ class ScrollSpyDirective {
222
+ constructor() {
223
+ this.itemId = input.required({ alias: 'uniScrollSpy' });
224
+ this.scrollElement = input('window');
225
+ this.classActive = signal(false);
226
+ this._el = inject(ElementRef);
227
+ this._scrollSpyService = inject(ScrollSpyService);
228
+ this._destroyRef = inject(DestroyRef);
229
+ }
230
+ ngOnDestroy() {
231
+ this._scrollSpyService.deleteItem(this.itemId());
232
+ }
233
+ ngAfterViewInit() {
234
+ this._scrollSpyService
235
+ .observe(this.scrollElement())
236
+ .pipe(takeUntilDestroyed(this._destroyRef))
237
+ .subscribe((element) => {
238
+ if (element != null) {
239
+ this.classActive.set(element.id === this.itemId());
240
+ }
241
+ });
242
+ this._scrollSpyService.setItem(this.itemId(), this._el, this.scrollElement());
243
+ const keyType = this._scrollSpyService.attributeType === 'data-id' ? 'data-id' : 'id';
244
+ this._el.nativeElement.setAttribute(keyType, this.itemId());
245
+ }
246
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollSpyDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
247
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.19", type: ScrollSpyDirective, isStandalone: true, selector: "[uniScrollSpy]", inputs: { itemId: { classPropertyName: "itemId", publicName: "uniScrollSpy", isSignal: true, isRequired: true, transformFunction: null }, scrollElement: { classPropertyName: "scrollElement", publicName: "scrollElement", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.active": "classActive()" } }, ngImport: i0 }); }
248
+ }
249
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollSpyDirective, decorators: [{
250
+ type: Directive,
251
+ args: [{
252
+ selector: '[uniScrollSpy]',
253
+ standalone: true,
254
+ host: {
255
+ '[class.active]': 'classActive()'
256
+ }
257
+ }]
258
+ }] });
259
+
260
+ class ScrollElementDirective {
261
+ constructor() {
262
+ this.elementId = input.required({ alias: 'uniScrollElement' });
263
+ this.direction = input(ScrollDirectionEnum.vertical);
264
+ this.scrollSpyElements = contentChildren(ScrollSpyDirective, { descendants: true });
265
+ this._el = inject(ElementRef);
266
+ this._scrollSpyService = inject(ScrollSpyService);
267
+ }
268
+ onScroll() {
269
+ this._scrollSpyService.updateScrollElement(this.elementId());
270
+ }
271
+ ngOnInit() {
272
+ this._scrollSpyService.setScrollElement(this.elementId(), this._el, this.direction());
273
+ if (this._scrollSpyService.attributeType === 'id') {
274
+ this._el.nativeElement.setAttribute('id', this.elementId());
275
+ }
276
+ else {
277
+ this._el.nativeElement.setAttribute('data-id', this.elementId());
278
+ }
279
+ }
280
+ ngAfterViewInit() {
281
+ const elements = this.scrollSpyElements();
282
+ elements.forEach((element) => {
283
+ this._scrollSpyService.changeScrollElement(element.itemId(), element.scrollElement(), this.elementId());
284
+ });
285
+ }
286
+ ngOnDestroy() {
287
+ this._scrollSpyService.deleteScrollElement(this.elementId());
288
+ }
289
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollElementDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
290
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "19.2.19", type: ScrollElementDirective, isStandalone: true, selector: "[uniScrollElement]", inputs: { elementId: { classPropertyName: "elementId", publicName: "uniScrollElement", isSignal: true, isRequired: true, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "scroll": "onScroll()" } }, queries: [{ propertyName: "scrollSpyElements", predicate: ScrollSpyDirective, descendants: true, isSignal: true }], ngImport: i0 }); }
291
+ }
292
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollElementDirective, decorators: [{
293
+ type: Directive,
294
+ args: [{
295
+ selector: '[uniScrollElement]',
296
+ standalone: true,
297
+ host: {
298
+ '(scroll)': 'onScroll()'
299
+ }
300
+ }]
301
+ }] });
302
+
303
+ class ScrollItemDirective {
304
+ constructor() {
305
+ this.itemId = input.required({ alias: 'uniScrollItem' });
306
+ this.scrollElement = input('window');
307
+ this.activeEvent = output();
308
+ this.classActive = signal(false);
309
+ this._scrollSpyService = inject(ScrollSpyService);
310
+ this._destroyRef = inject(DestroyRef);
311
+ }
312
+ ngAfterViewInit() {
313
+ this._scrollSpyService
314
+ .observe(this.scrollElement())
315
+ .pipe(takeUntilDestroyed(this._destroyRef))
316
+ .subscribe((element) => {
317
+ let _active;
318
+ if (element != null) {
319
+ _active = element.id === this.itemId();
320
+ this.activeEvent.emit(_active);
321
+ }
322
+ else {
323
+ _active = false;
324
+ }
325
+ this.classActive.set(_active);
326
+ });
327
+ }
328
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
329
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.19", type: ScrollItemDirective, isStandalone: true, selector: "[uniScrollItem]", inputs: { itemId: { classPropertyName: "itemId", publicName: "uniScrollItem", isSignal: true, isRequired: true, transformFunction: null }, scrollElement: { classPropertyName: "scrollElement", publicName: "scrollElement", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeEvent: "activeEvent" }, host: { properties: { "class.active": "classActive()" } }, ngImport: i0 }); }
330
+ }
331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: ScrollItemDirective, decorators: [{
332
+ type: Directive,
333
+ args: [{
334
+ selector: '[uniScrollItem]',
335
+ standalone: true,
336
+ host: {
337
+ '[class.active]': 'classActive()'
338
+ }
339
+ }]
340
+ }] });
341
+
342
+ const directives = [ScrollSpyDirective, ScrollItemDirective, ScrollElementDirective];
343
+ /**
344
+ * Provide ScrollSpy configuration for standalone applications.
345
+ *
346
+ * @example
347
+ * ```typescript
348
+ * bootstrapApplication(AppComponent, {
349
+ * providers: [provideScrollSpy({ lookAhead: true })]
350
+ * });
351
+ * ```
352
+ */
353
+ function provideScrollSpy(config = { lookAhead: false }) {
354
+ return makeEnvironmentProviders([{ provide: SPY_CONFIG, useValue: config }]);
355
+ }
356
+ /**
357
+ * @deprecated Use standalone directives (ScrollSpyDirective, ScrollItemDirective, ScrollElementDirective)
358
+ * and provideScrollSpy() instead.
359
+ */
360
+ class NgxScrollspyModule {
361
+ static forRoot(parameters = { lookAhead: false }) {
362
+ return {
363
+ ngModule: NgxScrollspyModule,
364
+ providers: [{ provide: SPY_CONFIG, useValue: parameters }]
365
+ };
366
+ }
367
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: NgxScrollspyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
368
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.19", ngImport: i0, type: NgxScrollspyModule, imports: [ScrollSpyDirective, ScrollItemDirective, ScrollElementDirective], exports: [ScrollSpyDirective, ScrollItemDirective, ScrollElementDirective] }); }
369
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: NgxScrollspyModule }); }
370
+ }
371
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: NgxScrollspyModule, decorators: [{
372
+ type: NgModule,
373
+ args: [{
374
+ imports: [...directives],
375
+ exports: [...directives]
376
+ }]
377
+ }] });
378
+
379
+ /*
380
+ * Public API Surface of ngx-scrollspy
381
+ */
382
+ // enums
383
+
384
+ /**
385
+ * Generated bundle index. Do not edit.
386
+ */
387
+
388
+ export { NgxScrollspyModule, SPY_CONFIG, ScrollDirectionEnum, ScrollElementDirective, ScrollItemDirective, ScrollSpyDirective, ScrollSpyService, provideScrollSpy };
389
+ //# sourceMappingURL=uniprank-ngx-scrollspy.mjs.map