@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.
- package/README.md +102 -81
- package/fesm2022/uniprank-ngx-scrollspy.mjs +389 -0
- package/fesm2022/uniprank-ngx-scrollspy.mjs.map +1 -0
- package/index.d.ts +6 -0
- package/lib/ngx-scrollspy.module.d.ts +24 -1
- package/lib/ngx-scrollspy.module.d.ts.map +1 -0
- package/lib/scroll-direction.enum.d.ts +1 -0
- package/lib/scroll-direction.enum.d.ts.map +1 -0
- package/lib/scroll-element.directive.d.ts +12 -9
- package/lib/scroll-element.directive.d.ts.map +1 -0
- package/lib/scroll-element.interface.d.ts +1 -0
- package/lib/scroll-element.interface.d.ts.map +1 -0
- package/lib/scroll-item.directive.d.ts +12 -12
- package/lib/scroll-item.directive.d.ts.map +1 -0
- package/lib/scroll-object.interface.d.ts +1 -0
- package/lib/scroll-object.interface.d.ts.map +1 -0
- package/lib/scroll-spy.directive.d.ts +11 -10
- package/lib/scroll-spy.directive.d.ts.map +1 -0
- package/lib/scroll-spy.service.d.ts +13 -10
- package/lib/scroll-spy.service.d.ts.map +1 -0
- package/package.json +22 -15
- package/public-api.d.ts +3 -1
- package/public-api.d.ts.map +1 -0
- package/uniprank-ngx-scrollspy.d.ts.map +1 -0
- package/CHANGELOG.md +0 -26
- package/bundles/uniprank-ngx-scrollspy.umd.js +0 -649
- package/bundles/uniprank-ngx-scrollspy.umd.js.map +0 -1
- package/bundles/uniprank-ngx-scrollspy.umd.min.js +0 -16
- package/bundles/uniprank-ngx-scrollspy.umd.min.js.map +0 -1
- package/esm2015/lib/ngx-scrollspy.module.js +0 -28
- package/esm2015/lib/scroll-direction.enum.js +0 -6
- package/esm2015/lib/scroll-element.directive.js +0 -63
- package/esm2015/lib/scroll-element.interface.js +0 -1
- package/esm2015/lib/scroll-item.directive.js +0 -61
- package/esm2015/lib/scroll-object.interface.js +0 -1
- package/esm2015/lib/scroll-spy.directive.js +0 -60
- package/esm2015/lib/scroll-spy.service.js +0 -210
- package/esm2015/public-api.js +0 -14
- package/esm2015/uniprank-ngx-scrollspy.js +0 -6
- package/esm5/lib/ngx-scrollspy.module.js +0 -33
- package/esm5/lib/scroll-direction.enum.js +0 -6
- package/esm5/lib/scroll-element.directive.js +0 -65
- package/esm5/lib/scroll-element.interface.js +0 -1
- package/esm5/lib/scroll-item.directive.js +0 -63
- package/esm5/lib/scroll-object.interface.js +0 -1
- package/esm5/lib/scroll-spy.directive.js +0 -62
- package/esm5/lib/scroll-spy.service.js +0 -219
- package/esm5/public-api.js +0 -14
- package/esm5/uniprank-ngx-scrollspy.js +0 -6
- package/fesm2015/uniprank-ngx-scrollspy.js +0 -415
- package/fesm2015/uniprank-ngx-scrollspy.js.map +0 -1
- package/fesm5/uniprank-ngx-scrollspy.js +0 -435
- package/fesm5/uniprank-ngx-scrollspy.js.map +0 -1
- package/uniprank-ngx-scrollspy.d.ts +0 -5
- package/uniprank-ngx-scrollspy.metadata.json +0 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
[](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
|
|
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
|
-
|
|
17
|
+
## Setup (Standalone API)
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
bootstrapApplication(AppComponent, appConfig);
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then import the standalone directives directly in your components:
|
|
34
43
|
|
|
35
|
-
|
|
44
|
+
```typescript
|
|
45
|
+
import { Component } from '@angular/core';
|
|
46
|
+
import { ScrollSpyDirective, ScrollItemDirective } from '@uniprank/ngx-scrollspy';
|
|
36
47
|
|
|
37
|
-
@
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
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
|
|
72
|
+
Use `ScrollSpyDirective` to spy on window as default or set `scrollElement` to spy on another scrollable element.
|
|
50
73
|
|
|
51
|
-
```
|
|
52
|
-
import {
|
|
53
|
-
import {
|
|
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
|
-
|
|
60
|
-
|
|
79
|
+
selector: 'app-example',
|
|
80
|
+
standalone: true,
|
|
81
|
+
imports: [ScrollSpyDirective, ScrollItemDirective],
|
|
82
|
+
template: `<div uniScrollSpy="section-abc"></div>`
|
|
61
83
|
})
|
|
62
|
-
export class
|
|
63
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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 `
|
|
87
|
-
This unique id is called elementID and you need this elementID to connect your `
|
|
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
|
-
```
|
|
90
|
-
import {
|
|
91
|
-
import {
|
|
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
|
-
|
|
111
|
+
selector: 'app-example',
|
|
112
|
+
standalone: true,
|
|
113
|
+
imports: [ScrollSpyDirective, ScrollItemDirective, ScrollElementDirective],
|
|
96
114
|
template: `
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
104
|
-
|
|
105
|
-
constructor(private _scrollSpyService: ScrollSpyService) {}
|
|
122
|
+
export class ExampleComponent implements AfterViewInit {
|
|
123
|
+
constructor(private _scrollSpyService: ScrollSpyService) {}
|
|
106
124
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
|
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
|