@inizioevoke/astro-core 1.3.5 → 1.4.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/package.json
CHANGED
|
@@ -38,7 +38,7 @@ if (innerWidth) {
|
|
|
38
38
|
contentAttrs.style = `width:${typeof innerWidth == 'number' || /^\d+$/.test(innerWidth) ? `${innerWidth}px` : innerWidth};`
|
|
39
39
|
}
|
|
40
40
|
---
|
|
41
|
-
<
|
|
41
|
+
<scroll-container class:list={['evo-scroll-container', cssClass]} {...containerAttrs}>
|
|
42
42
|
<div class="evo-scroll-content" {...contentAttrs}>
|
|
43
43
|
<slot />
|
|
44
44
|
</div>
|
|
@@ -48,7 +48,7 @@ if (innerWidth) {
|
|
|
48
48
|
{horizontal && <div class="evo-scroll-track evo-scroll-track-x">
|
|
49
49
|
<div class="evo-scroll-thumb"></div>
|
|
50
50
|
</div>}
|
|
51
|
-
</
|
|
51
|
+
</scroll-container>
|
|
52
52
|
|
|
53
53
|
<script>
|
|
54
54
|
import './ScrollContainer';
|
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
const intersectionObserver = new IntersectionObserver((entries) => {
|
|
4
|
+
entries.forEach((entry) => {
|
|
5
|
+
if (entry.isIntersecting) {
|
|
6
|
+
const sc = getScrollContainer(entry.target as HTMLElement);
|
|
7
|
+
if (sc) {
|
|
8
|
+
sc.refresh();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
},
|
|
13
|
+
{ threshold: 0.1 }
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const mutationObserver = new MutationObserver((mutations) => {
|
|
17
|
+
const containers = new Set<IScrollContainer>();
|
|
18
|
+
mutations.forEach((mutation) => {
|
|
19
|
+
const sc = getScrollContainer(mutation.target as HTMLElement);
|
|
20
|
+
if (sc) {
|
|
21
|
+
containers.add(sc);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
[...containers].forEach((container) => {
|
|
25
|
+
container.refresh();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
1
29
|
export interface IScrollContainer {
|
|
2
30
|
scroll(args?: { left?: number | string, top?: number | string, behavior?: 'auto' | 'instant' | 'smooth' }): void;
|
|
3
31
|
getScroll(): { left: number, top: number }
|
|
@@ -5,64 +33,126 @@ export interface IScrollContainer {
|
|
|
5
33
|
refresh(): void;
|
|
6
34
|
}
|
|
7
35
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
36
|
+
|
|
37
|
+
export class ScrollContainer extends HTMLElement implements IScrollContainer {
|
|
38
|
+
// #container: HTMLElement & { evoScrollContainer: ScrollContainer };
|
|
39
|
+
#content!: HTMLElement;
|
|
40
|
+
#track!: HTMLElement;
|
|
41
|
+
#thumb!: HTMLElement;
|
|
42
|
+
#isDragging: boolean = false;
|
|
43
|
+
#startY: number = 0;
|
|
44
|
+
#startScrollTop: number = 0;
|
|
16
45
|
|
|
46
|
+
#scrollbarSettings: ScrollbarSettings = {};
|
|
17
47
|
#mouseupHandler: any = undefined;
|
|
18
48
|
#mousemoveHandler: any = undefined;
|
|
19
49
|
|
|
20
|
-
constructor(
|
|
50
|
+
constructor() {
|
|
51
|
+
super();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
connectedCallback() {
|
|
21
55
|
// const _this = this;
|
|
22
|
-
this.#container = container;
|
|
23
|
-
this.#
|
|
24
|
-
this.#
|
|
25
|
-
this.#
|
|
56
|
+
// this.#container = container as HTMLElement & { evoScrollContainer: ScrollContainer };
|
|
57
|
+
// this.#container.evoScrollContainer = this;
|
|
58
|
+
this.#content = this.querySelector('.evo-scroll-content') as HTMLElement;
|
|
59
|
+
this.#track = this.querySelector('.evo-scroll-track') as HTMLElement;
|
|
60
|
+
this.#thumb = this.querySelector('.evo-scroll-thumb') as HTMLElement;
|
|
26
61
|
this.#isDragging = false;
|
|
27
62
|
this.#startY = 0;
|
|
28
63
|
this.#startScrollTop = 0;
|
|
29
64
|
|
|
30
65
|
this.#thumb.addEventListener('mousedown', this.#thumbMouseDown.bind(this), { passive: true });
|
|
31
66
|
this.#content.addEventListener('scroll', this.#scrollContent.bind(this), { passive: true });
|
|
67
|
+
|
|
68
|
+
intersectionObserver.observe(this);
|
|
69
|
+
mutationObserver.observe(this, { attributes: true, childList: true, subtree: true });
|
|
70
|
+
|
|
71
|
+
window.addEventListener('resize', this.refresh.bind(this), { passive: true });
|
|
32
72
|
}
|
|
33
73
|
|
|
34
|
-
scroll({ left, top, behavior = 'auto' }: { left?: number | string, top?: number | string, behavior?: 'auto' | 'instant' | 'smooth' } = {}) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
74
|
+
// scroll({ left, top, behavior = 'auto' }: { left?: number | string, top?: number | string, behavior?: 'auto' | 'instant' | 'smooth' } = {}) {
|
|
75
|
+
// const current = this.getScroll();
|
|
76
|
+
// if (typeof left == 'string') {
|
|
77
|
+
// if (/^[\+\-]=?\d+/.test(left)) {
|
|
78
|
+
// left = current.left + parseInt(left.replace(/=/,''), 10);
|
|
79
|
+
// } else {
|
|
80
|
+
// left = parseInt(left, 10);
|
|
81
|
+
// }
|
|
82
|
+
// if (isNaN(left)) {
|
|
83
|
+
// left = undefined;
|
|
84
|
+
// }
|
|
85
|
+
// }
|
|
86
|
+
// if (typeof top == 'string') {
|
|
87
|
+
// if (/^[\+\-]=?\d+/.test(top)) {
|
|
88
|
+
// top = current.top + parseInt(top.replace(/=/,''), 10);
|
|
89
|
+
// } else {
|
|
90
|
+
// top = parseInt(top, 10);
|
|
91
|
+
// }
|
|
92
|
+
// if (isNaN(top)) {
|
|
93
|
+
// top = undefined;
|
|
94
|
+
// }
|
|
95
|
+
// }
|
|
96
|
+
// left = left ?? current.left;
|
|
97
|
+
// top = top ?? current.top;
|
|
98
|
+
// if (left < 0) {
|
|
99
|
+
// left = 0;
|
|
100
|
+
// }
|
|
101
|
+
// if (top < 0) {
|
|
102
|
+
// top = 0;
|
|
103
|
+
// }
|
|
104
|
+
// this.#content.scroll({ left: left, top: top, behavior });
|
|
105
|
+
// }
|
|
106
|
+
|
|
107
|
+
scroll(opts?: ScrollToOptions): void;
|
|
108
|
+
scroll(x: number, y: number): void;
|
|
109
|
+
scroll(...args: any[]) {
|
|
110
|
+
this.#content.scroll(...args);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
scrollTo(opts?: ScrollToOptions): void;
|
|
114
|
+
scrollTo(x: number, y: number): void;
|
|
115
|
+
scrollTo(...args: any[]) {
|
|
116
|
+
this.scroll(...args);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
scrollBy(opts?: ScrollToOptions): void;
|
|
120
|
+
scrollBy(x: number, y: number): void;
|
|
121
|
+
scrollBy(...args: any[]) {
|
|
122
|
+
this.#content.scrollBy(...args);
|
|
123
|
+
// let opts: ScrollToOptions = {};
|
|
124
|
+
// if (args.length === 1) {
|
|
125
|
+
// opts = args[0] as ScrollToOptions;
|
|
126
|
+
// } else if (args.length == 2) {
|
|
127
|
+
// opts.left = args[0];
|
|
128
|
+
// opts.top = args[1];
|
|
129
|
+
// }
|
|
130
|
+
// const current = this.getScroll();
|
|
131
|
+
// opts.left = current.left + (opts.left ?? 0);
|
|
132
|
+
// opts.top = current.top + (opts.top ?? 0);
|
|
133
|
+
// this.scroll(opts);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
get scrollLeft() {
|
|
137
|
+
return this.#content.scrollLeft;
|
|
138
|
+
}
|
|
139
|
+
set scrollLeft(value: number) {
|
|
140
|
+
this.scroll({ left: value });
|
|
141
|
+
}
|
|
142
|
+
get scrollTop() {
|
|
143
|
+
return this.#content.scrollTop;
|
|
144
|
+
}
|
|
145
|
+
set scrollTop(value: number) {
|
|
146
|
+
this.scroll({ top: value });
|
|
147
|
+
}
|
|
148
|
+
get scrollWidth() {
|
|
149
|
+
return this.#content.scrollWidth;
|
|
150
|
+
}
|
|
151
|
+
get scrollHeight() {
|
|
152
|
+
return this.#content.scrollHeight;
|
|
65
153
|
}
|
|
154
|
+
|
|
155
|
+
|
|
66
156
|
|
|
67
157
|
getScroll() {
|
|
68
158
|
return {
|
|
@@ -73,22 +163,38 @@ class ScrollContainer implements IScrollContainer {
|
|
|
73
163
|
|
|
74
164
|
resize({ height }: { height?: number }) {
|
|
75
165
|
if (typeof height == 'number') {
|
|
76
|
-
this
|
|
166
|
+
this.style.height = `${height}px`;
|
|
77
167
|
refresh();
|
|
78
168
|
}
|
|
79
169
|
}
|
|
80
170
|
|
|
171
|
+
configureScrollbar({ trackVisible, thumbHeight }: ScrollbarSettings) {
|
|
172
|
+
this.#scrollbarSettings = { trackVisible, thumbHeight };
|
|
173
|
+
this.refresh();
|
|
174
|
+
}
|
|
175
|
+
resetScrollbar() {
|
|
176
|
+
this.configureScrollbar({});
|
|
177
|
+
}
|
|
81
178
|
refresh() {
|
|
82
179
|
this.#updateThumbSize();
|
|
83
180
|
}
|
|
84
181
|
|
|
85
182
|
#updateThumbSize() {
|
|
86
183
|
const scrollHeight = this.#content.scrollHeight - getPaddingY(this.#content);
|
|
87
|
-
const containerHeight = this
|
|
184
|
+
const containerHeight = this.clientHeight - getPaddingY(this);
|
|
88
185
|
const visibleRatio = containerHeight / scrollHeight;
|
|
89
|
-
const thumbHeight =
|
|
90
|
-
this.#
|
|
91
|
-
|
|
186
|
+
const thumbHeight = visibleRatio * containerHeight;
|
|
187
|
+
if (this.#scrollbarSettings.thumbHeight != undefined) {
|
|
188
|
+
this.#thumb.style.height = `${this.#scrollbarSettings.thumbHeight < 0 ? 0 : this.#scrollbarSettings.thumbHeight > containerHeight ? containerHeight : this.#scrollbarSettings.thumbHeight}px`;
|
|
189
|
+
} else {
|
|
190
|
+
this.#thumb.style.height = `${thumbHeight > 20 ? thumbHeight : 20}px`;
|
|
191
|
+
}
|
|
192
|
+
if (this.#scrollbarSettings.trackVisible !== undefined) {
|
|
193
|
+
this.#track.style.display = this.#scrollbarSettings.trackVisible === true ? 'block' : 'none';
|
|
194
|
+
} else {
|
|
195
|
+
this.#track.style.display = visibleRatio < 1 ? 'block' : 'none';
|
|
196
|
+
}
|
|
197
|
+
|
|
92
198
|
}
|
|
93
199
|
|
|
94
200
|
#thumbMouseDown(e: MouseEvent) {
|
|
@@ -108,8 +214,8 @@ class ScrollContainer implements IScrollContainer {
|
|
|
108
214
|
if (this.#isDragging) {
|
|
109
215
|
const deltaY = e.clientY - this.#startY;
|
|
110
216
|
const scrollRatio =
|
|
111
|
-
(this.#content.scrollHeight - this
|
|
112
|
-
(this
|
|
217
|
+
(this.#content.scrollHeight - this.clientHeight) /
|
|
218
|
+
(this.clientHeight - this.#thumb.clientHeight);
|
|
113
219
|
this.#content.scrollTop = this.#startScrollTop + deltaY * scrollRatio;
|
|
114
220
|
} else {
|
|
115
221
|
this.#mouseDetach();
|
|
@@ -126,12 +232,13 @@ class ScrollContainer implements IScrollContainer {
|
|
|
126
232
|
|
|
127
233
|
#scrollContent() {
|
|
128
234
|
const scrollHeight = this.#content.scrollHeight - getPaddingY(this.#content);
|
|
129
|
-
const containerHeight = this
|
|
235
|
+
const containerHeight = this.clientHeight - getPaddingY(this);
|
|
130
236
|
const scrollRatio = this.#content.scrollTop / (scrollHeight - containerHeight);
|
|
131
237
|
const top = scrollRatio * (this.#track.clientHeight - this.#thumb.clientHeight);
|
|
132
238
|
this.#thumb.style.top = `${top}px`;
|
|
133
239
|
}
|
|
134
240
|
}
|
|
241
|
+
customElements.define('scroll-container', ScrollContainer);
|
|
135
242
|
|
|
136
243
|
export function resize(selector: string | HTMLElement | ScrollContainer, { height }: { height?: number }) {
|
|
137
244
|
if (typeof height == 'number') {
|
|
@@ -176,23 +283,30 @@ export function getScrollContainer(selector: string | HTMLElement | ScrollContai
|
|
|
176
283
|
if (selector instanceof ScrollContainer) {
|
|
177
284
|
return selector;
|
|
178
285
|
}
|
|
179
|
-
const
|
|
180
|
-
return
|
|
286
|
+
const scrollContainer = typeof selector == 'string' ? document.querySelector<HTMLElement>(selector) : selector;
|
|
287
|
+
return scrollContainer instanceof ScrollContainer ? scrollContainer as IScrollContainer : undefined;
|
|
288
|
+
// const key = typeof selector == 'string' ? document.querySelector<HTMLElement>(selector) : selector;
|
|
289
|
+
// return key ? scrollContainers.get(key) : undefined;
|
|
181
290
|
}
|
|
182
291
|
|
|
183
|
-
export function createScrollContainer(selector: string | HTMLElement): IScrollContainer | undefined {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
292
|
+
// export function createScrollContainer(selector: string | HTMLElement): IScrollContainer | undefined {
|
|
293
|
+
// const container = typeof selector == 'string' ? document.querySelector<HTMLElement>(selector) : selector;
|
|
294
|
+
// if (container) {
|
|
295
|
+
// if (scrollContainers.has(container)) {
|
|
296
|
+
// return scrollContainers.get(container);
|
|
297
|
+
// } else {
|
|
298
|
+
// const scrollContainer = new ScrollContainer(container);
|
|
299
|
+
// initNewScrollContainer(container, scrollContainer);
|
|
300
|
+
// return scrollContainer;
|
|
301
|
+
// }
|
|
302
|
+
// } else {
|
|
303
|
+
// return undefined;
|
|
304
|
+
// }
|
|
305
|
+
// }
|
|
306
|
+
|
|
307
|
+
interface ScrollbarSettings {
|
|
308
|
+
trackVisible?: boolean;
|
|
309
|
+
thumbHeight?: number;
|
|
196
310
|
}
|
|
197
311
|
|
|
198
312
|
function getPaddingY(content: HTMLElement): number {
|
|
@@ -200,48 +314,25 @@ function getPaddingY(content: HTMLElement): number {
|
|
|
200
314
|
return parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
|
|
201
315
|
}
|
|
202
316
|
|
|
203
|
-
const scrollContainers = new Map<HTMLElement, ScrollContainer>();
|
|
317
|
+
// const scrollContainers = new Map<HTMLElement, ScrollContainer>();
|
|
204
318
|
|
|
205
|
-
const intersectionObserver = new IntersectionObserver((entries) => {
|
|
206
|
-
entries.forEach((entry) => {
|
|
207
|
-
if (entry.isIntersecting) {
|
|
208
|
-
const sc = getScrollContainer(entry.target as HTMLElement);
|
|
209
|
-
if (sc) {
|
|
210
|
-
sc.refresh();
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
},
|
|
215
|
-
{ threshold: 0.1 }
|
|
216
|
-
);
|
|
217
319
|
|
|
218
|
-
const mutationObserver = new MutationObserver((mutations) => {
|
|
219
|
-
const containers = new Set<IScrollContainer>();
|
|
220
|
-
mutations.forEach((mutation) => {
|
|
221
|
-
const sc = getScrollContainer(mutation.target as HTMLElement);
|
|
222
|
-
if (sc) {
|
|
223
|
-
containers.add(sc);
|
|
224
|
-
}
|
|
225
|
-
});
|
|
226
|
-
[...containers].forEach((container) => {
|
|
227
|
-
container.refresh();
|
|
228
|
-
});
|
|
229
|
-
});
|
|
230
320
|
|
|
231
|
-
function initNewScrollContainer(container: HTMLElement, scrollContainer: ScrollContainer) {
|
|
232
|
-
|
|
321
|
+
// function initNewScrollContainer(container: HTMLElement, scrollContainer: ScrollContainer) {
|
|
322
|
+
// scrollContainers.set(container, scrollContainer);
|
|
233
323
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
324
|
+
// intersectionObserver.observe(container);
|
|
325
|
+
// mutationObserver.observe(container, { attributes: true, childList: true, subtree: true });
|
|
326
|
+
// }
|
|
237
327
|
|
|
238
|
-
document.querySelectorAll<HTMLElement>('.evo-scroll-container').forEach((container) => {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
});
|
|
328
|
+
// document.querySelectorAll<HTMLElement>('.evo-scroll-container').forEach((container) => {
|
|
329
|
+
// const scrollContainer = new ScrollContainer(container);
|
|
330
|
+
// initNewScrollContainer(container, scrollContainer);
|
|
331
|
+
// });
|
|
242
332
|
|
|
243
|
-
window.addEventListener('resize', () => {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
333
|
+
// window.addEventListener('resize', () => {
|
|
334
|
+
// // [...scrollContainers.values()].forEach((scrollContainer) => {
|
|
335
|
+
// [...document.querySelectorAll<ScrollContainer>('scroll-container')].forEach((scrollContainer) => {
|
|
336
|
+
// scrollContainer.refresh();
|
|
337
|
+
// });
|
|
338
|
+
// }, { passive: true });
|