@inizioevoke/astro-core 1.2.0 → 1.3.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inizioevoke/astro-core",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -1,6 +1,6 @@
1
1
  import * as pdfjs from './pdf.min.mjs';
2
2
  import type { PDFDocumentProxy } from 'pdfjs-dist';
3
- import * as ScrollContainer from '../ScrollContainer/ScrollContainer';
3
+ import * as ScrollContainer from '../ScrollContainer/archive-20260417';
4
4
 
5
5
  pdfjs.GlobalWorkerOptions.workerSrc = './pdf.worker.min.mjs';
6
6
 
@@ -1,104 +1,225 @@
1
+ export class ScrollContainer {
2
+ #container: HTMLElement;
3
+ #content: HTMLElement;
4
+ #track: HTMLElement;
5
+ #thumb: HTMLElement;
6
+ #isDragging: boolean;
7
+ #startY: number;
8
+ #startScrollTop: number;
9
+ // #enabled: boolean;
10
+
11
+ #mouseupHandler: any = undefined; // [] = [];
12
+ #mousemoveHandler: any = undefined; // [] = [];
13
+
14
+ constructor(container: HTMLElement) { // , { enabled }: { enabled?: boolean } = {}) {
15
+ const _this = this;
16
+ this.#container = container;
17
+ this.#content = container.querySelector('.evo-scroll-content') as HTMLElement;
18
+ this.#track = container.querySelector('.evo-scroll-track') as HTMLElement;
19
+ this.#thumb = container.querySelector('.evo-scroll-thumb') as HTMLElement;
20
+ this.#isDragging = false;
21
+ this.#startY = 0;
22
+ this.#startScrollTop = 0;
23
+ // this.#enabled = enabled ?? true;
24
+
25
+ this.#thumb.addEventListener('mousedown', (e) => {
26
+ _this.#thumbMouseDown(e);
27
+ }, { passive: true });
28
+
29
+ // this.#thumb.addEventListener('mouseup', (e) => {
30
+ // _this.#thumbMouseUp(e);
31
+ // }, { passive: true });
32
+
33
+ this.#content.addEventListener('scroll', () => {
34
+ _this.#scrollContent();
35
+ }, { passive: true });
36
+ }
37
+
38
+ // enable(flag?: boolean) {
39
+ // this.#enabled = flag ?? true;
40
+ // }
41
+ // get isEnabled() {
42
+ // return this.#enabled === true;
43
+ // }
44
+
45
+ scroll({ left, top, behavior = 'auto' }: { left?: number | string, top?: number | string, behavior?: 'auto' | 'instant' | 'smooth' } = {}) {
46
+ const current = this.getScroll();
47
+ if (typeof left == 'string') {
48
+ if (/^[\+\-]=?\d+/.test(left)) {
49
+ left = current.left + parseInt(left.replace(/=/,''), 10);
50
+ } else {
51
+ left = parseInt(left, 10);
52
+ }
53
+ if (isNaN(left)) {
54
+ left = undefined;
55
+ }
56
+ }
57
+ if (typeof top == 'string') {
58
+ if (/^[\+\-]=?\d+/.test(top)) {
59
+ top = current.top + parseInt(top.replace(/=/,''), 10);
60
+ } else {
61
+ top = parseInt(top, 10);
62
+ }
63
+ if (isNaN(top)) {
64
+ top = undefined;
65
+ }
66
+ }
67
+ left = left ?? current.left;
68
+ top = top ?? current.top;
69
+ if (left < 0) {
70
+ left = 0;
71
+ }
72
+ if (top < 0) {
73
+ top = 0;
74
+ }
75
+ this.#content.scroll({ left: left, top: top, behavior });
76
+ }
77
+
78
+ getScroll() {
79
+ return {
80
+ left: this.#content.scrollLeft,
81
+ top: this.#content.scrollTop
82
+ };
83
+ }
84
+
85
+ resize({ height }: { height?: number }) {
86
+ if (typeof height == 'number') {
87
+ this.#container.style.height = `${height}px`;
88
+ refresh();
89
+ }
90
+ }
91
+
92
+ refresh() {
93
+ this.#updateThumbSize();
94
+ }
95
+
96
+ #updateThumbSize() {
97
+ const scrollHeight = this.#content.scrollHeight - getPaddingY(this.#content);
98
+ const containerHeight = this.#container.clientHeight - getPaddingY(this.#container);
99
+ const visibleRatio = containerHeight / scrollHeight;
100
+ const thumbHeight = visibleRatio * containerHeight;
101
+ this.#thumb.style.height = `${thumbHeight > 20 ? thumbHeight : 20}px`;
102
+ this.#track.style.display = visibleRatio < 1 ? 'block' : 'none';
103
+ }
104
+
105
+ #thumbMouseDown(e: MouseEvent) {
106
+ this.#mouseupHandler = this.#mouseDetach.bind(this); // .push(this.#mouseDetach.bind(this));
107
+ this.#mousemoveHandler = this.#thumbMouseMove.bind(this); // .push(this.#thumbMouseMove.bind(this));
108
+ document.addEventListener('mouseup', this.#mouseupHandler, { passive: true }); // this.#mouseupHandler[this.#mouseupHandler.length - 1]);
109
+ document.addEventListener('dragend', this.#mouseupHandler, { passive: true }); // this.#mouseupHandler[this.#mouseupHandler.length - 1]);
110
+ document.addEventListener('mousemove', this.#mousemoveHandler, { passive: true }); // this.#mousemoveHandler[this.#mousemoveHandler.length - 1]);
111
+ this.#isDragging = true;
112
+ this.#startY = e.clientY;
113
+ this.#startScrollTop = this.#content.scrollTop;
114
+ this.#thumb.style.cursor = 'grabbing';
115
+ }
116
+
117
+ #thumbMouseMove(e: MouseEvent) {
118
+ // console.log(performance.now());
119
+ if (this.#isDragging) {
120
+ const deltaY = e.clientY - this.#startY;
121
+ const scrollRatio =
122
+ (this.#content.scrollHeight - this.#container.clientHeight) /
123
+ (this.#container.clientHeight - this.#thumb.clientHeight);
124
+ this.#content.scrollTop = this.#startScrollTop + deltaY * scrollRatio;
125
+ } else {
126
+ this.#mouseDetach();
127
+ }
128
+ }
129
+
130
+ // #thumbMouseUp(e: MouseEvent) {
131
+ // this.#isDragging = false;
132
+ // this.#thumb.style.cursor = 'grab';
133
+ // }
134
+
135
+ #mouseDetach() {
136
+ this.#isDragging = false;
137
+ this.#thumb.style.cursor = 'grab';
138
+ document.removeEventListener('mouseup', this.#mouseupHandler);
139
+ document.removeEventListener('dragend', this.#mouseupHandler);
140
+ document.removeEventListener('mousemove', this.#mousemoveHandler);
141
+ // for (const m of this.#mouseupHandler) {
142
+ // document.removeEventListener('mouseup', m);
143
+ // document.removeEventListener('dragend', m);
144
+ // }
145
+ // for (const m of this.#mousemoveHandler) {
146
+ // document.removeEventListener('mousemove', m);
147
+ // }
148
+ // this.#mouseupHandler = [];
149
+ // this.#mousemoveHandler = [];
150
+ }
151
+
152
+ #scrollContent() {
153
+ const scrollHeight = this.#content.scrollHeight - getPaddingY(this.#content);
154
+ const containerHeight = this.#container.clientHeight - getPaddingY(this.#container);
155
+ const scrollRatio = this.#content.scrollTop / (scrollHeight - containerHeight);
156
+ const top = scrollRatio * (this.#track.clientHeight - this.#thumb.clientHeight);
157
+ this.#thumb.style.top = `${top}px`;
158
+ }
1
159
 
2
- export interface IScrollContainer {
3
- container: HTMLElement;
4
- content: HTMLElement;
5
- track: HTMLElement;
6
- thumb: HTMLElement;
7
- isDragging: boolean;
8
- startY: number;
9
- startScrollTop: number;
10
160
  }
11
161
 
12
- export function resize(scrollContainer: IScrollContainer, { height }: { height?: number }) {
162
+ export function resize(scrollContainer: string | HTMLElement | ScrollContainer, { height }: { height?: number }) {
13
163
  if (typeof height == 'number') {
14
- scrollContainer.container.style.height = `${height}px`;
15
- refresh(scrollContainer);
164
+ const sc = getScrollContainer(scrollContainer);
165
+ if (sc) {
166
+ sc.resize({ height })
167
+ }
16
168
  }
17
169
  }
18
170
 
19
- export function refresh(scrollContainer?: IScrollContainer) {
171
+ export function refresh(scrollContainer?: string | HTMLElement | ScrollContainer) {
20
172
  if (scrollContainer) {
21
- updateThumbSize(scrollContainer);
173
+ const sc = getScrollContainer(scrollContainer);
174
+ if (sc) {
175
+ sc.refresh()
176
+ }
22
177
  } else {
23
178
  [...scrollContainers.values()].forEach((scrollContainer) => {
24
- updateThumbSize(scrollContainer);
179
+ scrollContainer.refresh();
25
180
  });
26
181
  }
27
182
  }
28
183
 
29
- export function getScroll(scrollContainer: IScrollContainer): { left: number, top: number } {
30
- return {
31
- left: scrollContainer.content.scrollLeft,
32
- top: scrollContainer.content.scrollTop
33
- };
184
+ export function getScroll(scrollContainer: string | HTMLElement | ScrollContainer): { left: number, top: number } | undefined {
185
+ const sc = getScrollContainer(scrollContainer);
186
+ if (sc) {
187
+ return sc.getScroll();
188
+ } else {
189
+ return undefined;
190
+ }
34
191
  }
35
- export function scroll(scrollContainer: IScrollContainer, { left, top, behavior = 'auto' }: { left?: number, top?: number, behavior?: 'auto' | 'instant' | 'smooth' } = {}) {
36
- const current = getScroll(scrollContainer);
37
- scrollContainer.content.scroll({ left: left ?? current.left, top: top ?? current.top, behavior });
192
+
193
+ export function scroll(scrollContainer: string | HTMLElement | ScrollContainer, { left, top, behavior = 'auto' }: { left?: number, top?: number, behavior?: 'auto' | 'instant' | 'smooth' } = {}) {
194
+ const sc = getScrollContainer(scrollContainer);
195
+ if (sc) {
196
+ const current = sc.getScroll();
197
+ sc.scroll({ left: left ?? current.left, top: top ?? current.top, behavior });
198
+ }
38
199
  }
39
200
 
40
- export function getScrollContainer(selector: string | HTMLElement): IScrollContainer | undefined {
201
+ export function getScrollContainer(selector: string | HTMLElement | ScrollContainer): ScrollContainer | undefined {
202
+ if (selector instanceof ScrollContainer) {
203
+ return selector;
204
+ }
41
205
  const key = typeof selector == 'string' ? document.querySelector<HTMLElement>(selector) : selector;
42
206
  return key ? scrollContainers.get(key) : undefined;
43
207
  }
44
208
 
45
- function thumbMouseDown(scrollContainer: IScrollContainer, e: MouseEvent) {
46
- scrollContainer.isDragging = true;
47
- scrollContainer.startY = e.clientY;
48
- scrollContainer.startScrollTop = scrollContainer.content.scrollTop;
49
- scrollContainer.thumb.style.cursor = 'grabbing';
50
- }
51
-
52
- function updateThumbSize(scrollContainer: IScrollContainer) {
53
- const { container, content, thumb, track } = scrollContainer;
54
- const scrollHeight = content.scrollHeight - getPaddingY(content);
55
- const containerHeight = container.clientHeight - getPaddingY(container);
56
- const visibleRatio = containerHeight / scrollHeight;
57
- const thumbHeight = visibleRatio * containerHeight;
58
- thumb.style.height = `${thumbHeight > 20 ? thumbHeight : 20}px`;
59
- track.style.display = visibleRatio < 1 ? 'block' : 'none';
60
- }
61
-
62
- function scrollContent(scrollContainer: IScrollContainer) {
63
- const { container, content, thumb, track } = scrollContainer;
64
- const scrollHeight = content.scrollHeight - getPaddingY(content);
65
- const containerHeight = container.clientHeight - getPaddingY(container);
66
- const scrollRatio = content.scrollTop / (scrollHeight - containerHeight);
67
- const top = scrollRatio * (track.clientHeight - thumb.clientHeight);
68
- thumb.style.top = `${top}px`;
69
- }
70
-
71
209
  function getPaddingY(content: HTMLElement): number {
72
210
  const style = getComputedStyle(content);
73
211
  return parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
74
212
  }
75
213
 
76
- function getScrollContainerElement(element: HTMLElement) {
77
- let container = element;
78
- while (container && !container.classList.contains('scroll-container')) {
79
- container = container.parentElement as HTMLElement;
80
- }
81
- return container;
82
- }
83
-
84
- function createScrollContainer(container: HTMLElement): IScrollContainer {
85
- return {
86
- container: container,
87
- content: container.querySelector('.evo-scroll-content') as HTMLElement,
88
- track: container.querySelector('.evo-scroll-track') as HTMLElement,
89
- thumb: container.querySelector('.evo-scroll-thumb') as HTMLElement,
90
- isDragging: false,
91
- startY: 0,
92
- startScrollTop: 0
93
- };
94
- }
95
-
96
- const scrollContainers = new Map<HTMLElement, IScrollContainer>();
214
+ const scrollContainers = new Map<HTMLElement, ScrollContainer>();
97
215
 
98
216
  const intersectionObserver = new IntersectionObserver((entries) => {
99
217
  entries.forEach((entry) => {
100
218
  if (entry.isIntersecting) {
101
- updateThumbSize(scrollContainers.get(entry.target as HTMLElement) as IScrollContainer);
219
+ const sc = getScrollContainer(entry.target as HTMLElement);
220
+ if (sc) {
221
+ sc.refresh();
222
+ }
102
223
  }
103
224
  });
104
225
  },
@@ -106,45 +227,28 @@ const intersectionObserver = new IntersectionObserver((entries) => {
106
227
  );
107
228
 
108
229
  const mutationObserver = new MutationObserver((mutations) => {
109
- const containers: IScrollContainer[] = [];
230
+ const containers = new Set<ScrollContainer>();
110
231
  mutations.forEach((mutation) => {
111
- const sc = scrollContainers.get(getScrollContainerElement(mutation.target as HTMLElement));
112
- if (sc && !containers.includes(sc)) {
113
- containers.push(sc);
232
+ const sc = getScrollContainer(mutation.target as HTMLElement);
233
+ if (sc) {
234
+ containers.add(sc);
114
235
  }
115
236
  });
116
- containers.forEach((container) => {
117
- updateThumbSize(container);
237
+ [...containers].forEach((container) => {
238
+ container.refresh();
118
239
  });
119
240
  });
120
241
 
121
242
  document.querySelectorAll<HTMLElement>('.evo-scroll-container').forEach((container) => {
122
- const scrollContainer = createScrollContainer(container);
243
+ const scrollContainer = new ScrollContainer(container);
123
244
  scrollContainers.set(container, scrollContainer);
124
- scrollContainer.thumb.addEventListener('mousedown', (e) => { thumbMouseDown(scrollContainer, e); }, { passive: true });
125
- scrollContainer.content.addEventListener('scroll', (e) => { scrollContent(scrollContainer); }, { passive: true });
245
+
126
246
  intersectionObserver.observe(container);
127
- mutationObserver.observe(container, { childList: true, subtree: true });
128
- });
129
- document.addEventListener('mousemove', (e) => {
130
- [...scrollContainers.values()].forEach((scrollContainer) => {
131
- if (!scrollContainer.isDragging) return;
132
- const { container, content, thumb } = scrollContainer;
133
- const deltaY = e.clientY - scrollContainer.startY;
134
- const scrollRatio =
135
- (content.scrollHeight - container.clientHeight) /
136
- (container.clientHeight - thumb.clientHeight);
137
- scrollContainer.content.scrollTop = scrollContainer.startScrollTop + deltaY * scrollRatio;
138
- });
139
- });
140
- document.addEventListener('mouseup', () => {
141
- [...scrollContainers.values()].forEach((scrollContainer) => {
142
- scrollContainer.isDragging = false;
143
- scrollContainer.thumb.style.cursor = 'grab';
144
- });
247
+ mutationObserver.observe(container, { attributes: true, childList: true, subtree: true });
145
248
  });
249
+
146
250
  window.addEventListener('resize', () => {
147
251
  [...scrollContainers.values()].forEach((scrollContainer) => {
148
- updateThumbSize(scrollContainer);
252
+ scrollContainer.refresh();
149
253
  });
150
254
  });
@@ -0,0 +1,150 @@
1
+
2
+ export interface IScrollContainer {
3
+ container: HTMLElement;
4
+ content: HTMLElement;
5
+ track: HTMLElement;
6
+ thumb: HTMLElement;
7
+ isDragging: boolean;
8
+ startY: number;
9
+ startScrollTop: number;
10
+ }
11
+
12
+ export function resize(scrollContainer: IScrollContainer, { height }: { height?: number }) {
13
+ if (typeof height == 'number') {
14
+ scrollContainer.container.style.height = `${height}px`;
15
+ refresh(scrollContainer);
16
+ }
17
+ }
18
+
19
+ export function refresh(scrollContainer?: IScrollContainer) {
20
+ if (scrollContainer) {
21
+ updateThumbSize(scrollContainer);
22
+ } else {
23
+ [...scrollContainers.values()].forEach((scrollContainer) => {
24
+ updateThumbSize(scrollContainer);
25
+ });
26
+ }
27
+ }
28
+
29
+ export function getScroll(scrollContainer: IScrollContainer): { left: number, top: number } {
30
+ return {
31
+ left: scrollContainer.content.scrollLeft,
32
+ top: scrollContainer.content.scrollTop
33
+ };
34
+ }
35
+ export function scroll(scrollContainer: IScrollContainer, { left, top, behavior = 'auto' }: { left?: number, top?: number, behavior?: 'auto' | 'instant' | 'smooth' } = {}) {
36
+ const current = getScroll(scrollContainer);
37
+ scrollContainer.content.scroll({ left: left ?? current.left, top: top ?? current.top, behavior });
38
+ }
39
+
40
+ export function getScrollContainer(selector: string | HTMLElement): IScrollContainer | undefined {
41
+ const key = typeof selector == 'string' ? document.querySelector<HTMLElement>(selector) : selector;
42
+ return key ? scrollContainers.get(key) : undefined;
43
+ }
44
+
45
+ function thumbMouseDown(scrollContainer: IScrollContainer, e: MouseEvent) {
46
+ scrollContainer.isDragging = true;
47
+ scrollContainer.startY = e.clientY;
48
+ scrollContainer.startScrollTop = scrollContainer.content.scrollTop;
49
+ scrollContainer.thumb.style.cursor = 'grabbing';
50
+ }
51
+
52
+ function updateThumbSize(scrollContainer: IScrollContainer) {
53
+ const { container, content, thumb, track } = scrollContainer;
54
+ const scrollHeight = content.scrollHeight - getPaddingY(content);
55
+ const containerHeight = container.clientHeight - getPaddingY(container);
56
+ const visibleRatio = containerHeight / scrollHeight;
57
+ const thumbHeight = visibleRatio * containerHeight;
58
+ thumb.style.height = `${thumbHeight > 20 ? thumbHeight : 20}px`;
59
+ track.style.display = visibleRatio < 1 ? 'block' : 'none';
60
+ }
61
+
62
+ function scrollContent(scrollContainer: IScrollContainer) {
63
+ const { container, content, thumb, track } = scrollContainer;
64
+ const scrollHeight = content.scrollHeight - getPaddingY(content);
65
+ const containerHeight = container.clientHeight - getPaddingY(container);
66
+ const scrollRatio = content.scrollTop / (scrollHeight - containerHeight);
67
+ const top = scrollRatio * (track.clientHeight - thumb.clientHeight);
68
+ thumb.style.top = `${top}px`;
69
+ }
70
+
71
+ function getPaddingY(content: HTMLElement): number {
72
+ const style = getComputedStyle(content);
73
+ return parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
74
+ }
75
+
76
+ function getScrollContainerElement(element: HTMLElement) {
77
+ let container = element;
78
+ while (container && !container.classList.contains('scroll-container')) {
79
+ container = container.parentElement as HTMLElement;
80
+ }
81
+ return container;
82
+ }
83
+
84
+ function createScrollContainer(container: HTMLElement): IScrollContainer {
85
+ return {
86
+ container: container,
87
+ content: container.querySelector('.evo-scroll-content') as HTMLElement,
88
+ track: container.querySelector('.evo-scroll-track') as HTMLElement,
89
+ thumb: container.querySelector('.evo-scroll-thumb') as HTMLElement,
90
+ isDragging: false,
91
+ startY: 0,
92
+ startScrollTop: 0
93
+ };
94
+ }
95
+
96
+ const scrollContainers = new Map<HTMLElement, IScrollContainer>();
97
+
98
+ const intersectionObserver = new IntersectionObserver((entries) => {
99
+ entries.forEach((entry) => {
100
+ if (entry.isIntersecting) {
101
+ updateThumbSize(scrollContainers.get(entry.target as HTMLElement) as IScrollContainer);
102
+ }
103
+ });
104
+ },
105
+ { threshold: 0.1 }
106
+ );
107
+
108
+ const mutationObserver = new MutationObserver((mutations) => {
109
+ const containers: IScrollContainer[] = [];
110
+ mutations.forEach((mutation) => {
111
+ const sc = scrollContainers.get(getScrollContainerElement(mutation.target as HTMLElement));
112
+ if (sc && !containers.includes(sc)) {
113
+ containers.push(sc);
114
+ }
115
+ });
116
+ containers.forEach((container) => {
117
+ updateThumbSize(container);
118
+ });
119
+ });
120
+
121
+ document.querySelectorAll<HTMLElement>('.evo-scroll-container').forEach((container) => {
122
+ const scrollContainer = createScrollContainer(container);
123
+ scrollContainers.set(container, scrollContainer);
124
+ scrollContainer.thumb.addEventListener('mousedown', (e) => { thumbMouseDown(scrollContainer, e); }, { passive: true });
125
+ scrollContainer.content.addEventListener('scroll', (e) => { scrollContent(scrollContainer); }, { passive: true });
126
+ intersectionObserver.observe(container);
127
+ mutationObserver.observe(container, { childList: true, subtree: true });
128
+ });
129
+ document.addEventListener('mousemove', (e) => {
130
+ [...scrollContainers.values()].forEach((scrollContainer) => {
131
+ if (!scrollContainer.isDragging) return;
132
+ const { container, content, thumb } = scrollContainer;
133
+ const deltaY = e.clientY - scrollContainer.startY;
134
+ const scrollRatio =
135
+ (content.scrollHeight - container.clientHeight) /
136
+ (container.clientHeight - thumb.clientHeight);
137
+ scrollContainer.content.scrollTop = scrollContainer.startScrollTop + deltaY * scrollRatio;
138
+ });
139
+ });
140
+ document.addEventListener('mouseup', () => {
141
+ [...scrollContainers.values()].forEach((scrollContainer) => {
142
+ scrollContainer.isDragging = false;
143
+ scrollContainer.thumb.style.cursor = 'grab';
144
+ });
145
+ });
146
+ window.addEventListener('resize', () => {
147
+ [...scrollContainers.values()].forEach((scrollContainer) => {
148
+ updateThumbSize(scrollContainer);
149
+ });
150
+ });