@hortonstudio/main 1.9.9 → 1.9.10
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/autoInit/accessibility/README.md +9 -1
- package/autoInit/accessibility/accessibility.js +2 -1
- package/autoInit/accessibility/functions/pagination/README.md +428 -0
- package/{utils/slider/slider.js → autoInit/accessibility/functions/pagination/pagination.js} +173 -242
- package/index.js +0 -2
- package/package.json +1 -1
- package/utils/before-after/README.md +352 -75
- package/utils/slider/README.md +0 -299
package/{utils/slider/slider.js → autoInit/accessibility/functions/pagination/pagination.js}
RENAMED
|
@@ -1,93 +1,80 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if (!wrapper || !nextBtn || !prevBtn) return;
|
|
8
|
-
const slides = wrapper.children;
|
|
9
|
-
if (!slides?.length) return;
|
|
10
|
-
|
|
11
|
-
const state = { currentIndex: 1, totalSlides: slides.length, isAnimating: false };
|
|
12
|
-
|
|
13
|
-
wrapper.appendChild(slides[0].cloneNode(true));
|
|
14
|
-
wrapper.insertBefore(slides[slides.length - 1].cloneNode(true), slides[0]);
|
|
15
|
-
|
|
16
|
-
gsap.set(wrapper, { xPercent: -100 });
|
|
1
|
+
/**
|
|
2
|
+
* Pagination System
|
|
3
|
+
*
|
|
4
|
+
* Handles paginated lists with controls, counters, and dot navigation.
|
|
5
|
+
* Supports infinite looping, responsive layouts, and accessibility.
|
|
6
|
+
*/
|
|
17
7
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
onComplete: () => {
|
|
31
|
-
if (isLoop) {
|
|
32
|
-
state.currentIndex = direction > 0 ? 1 : state.totalSlides;
|
|
33
|
-
gsap.set(wrapper, { xPercent: -state.currentIndex * 100 });
|
|
34
|
-
}
|
|
35
|
-
state.isAnimating = false;
|
|
8
|
+
export function init() {
|
|
9
|
+
const cleanup = {
|
|
10
|
+
observers: [],
|
|
11
|
+
handlers: []
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// Initialize all pagination containers
|
|
15
|
+
document.querySelectorAll('[data-hs-pagination="wrapper"]')
|
|
16
|
+
.forEach(container => {
|
|
17
|
+
const instance = initPaginationInstance(container, cleanup);
|
|
18
|
+
if (!instance) {
|
|
19
|
+
console.warn('[hs-pagination] Failed to initialize container', container);
|
|
36
20
|
}
|
|
37
21
|
});
|
|
38
|
-
};
|
|
39
22
|
|
|
40
|
-
|
|
41
|
-
|
|
23
|
+
return {
|
|
24
|
+
result: "pagination initialized",
|
|
25
|
+
destroy: () => {
|
|
26
|
+
// Disconnect all observers
|
|
27
|
+
cleanup.observers.forEach(obs => obs.disconnect());
|
|
28
|
+
cleanup.observers.length = 0;
|
|
42
29
|
|
|
43
|
-
|
|
44
|
-
|
|
30
|
+
// Remove all event listeners
|
|
31
|
+
cleanup.handlers.forEach(({ element, event, handler }) => {
|
|
32
|
+
element.removeEventListener(event, handler);
|
|
33
|
+
});
|
|
34
|
+
cleanup.handlers.length = 0;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
45
38
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
function initPaginationInstance(container, cleanup) {
|
|
40
|
+
const list = container.querySelector('[data-hs-pagination="list"]');
|
|
41
|
+
if (!list) {
|
|
42
|
+
console.warn('[hs-pagination] Missing required element: data-hs-pagination="list"');
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
51
45
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
document.querySelectorAll('[data-hs-slider="pagination"]')
|
|
55
|
-
.forEach(container => {
|
|
56
|
-
const list = container.querySelector('[data-hs-slider="pagination-list"]');
|
|
57
|
-
if (list) initPaginationInstance(list, container, cleanup);
|
|
58
|
-
});
|
|
59
|
-
};
|
|
46
|
+
const wrapper = list.parentElement;
|
|
47
|
+
if (!wrapper) return null;
|
|
60
48
|
|
|
61
|
-
const initPaginationInstance = (originalList, container, cleanup) => {
|
|
62
|
-
const wrapper = originalList.parentElement;
|
|
63
|
-
if (!wrapper || !container) return;
|
|
64
|
-
|
|
65
49
|
const elements = {
|
|
66
|
-
nextBtn: container.querySelector('[data-hs-
|
|
67
|
-
prevBtn: container.querySelector('[data-hs-
|
|
68
|
-
counter: container.querySelector('[data-hs-
|
|
69
|
-
controls: container.querySelector('[data-hs-
|
|
70
|
-
dotsWrap: container.querySelector('[data-hs-
|
|
50
|
+
nextBtn: container.querySelector('[data-hs-pagination="next"]'),
|
|
51
|
+
prevBtn: container.querySelector('[data-hs-pagination="previous"]'),
|
|
52
|
+
counter: container.querySelector('[data-hs-pagination="counter"]'),
|
|
53
|
+
controls: container.querySelector('[data-hs-pagination="controls"]'),
|
|
54
|
+
dotsWrap: container.querySelector('[data-hs-pagination="dots"]')
|
|
71
55
|
};
|
|
72
|
-
|
|
73
|
-
if (!elements.nextBtn || !elements.prevBtn)
|
|
74
|
-
|
|
56
|
+
|
|
57
|
+
if (!elements.nextBtn || !elements.prevBtn) {
|
|
58
|
+
console.warn('[hs-pagination] Missing required navigation buttons');
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Add ARIA attributes to buttons
|
|
75
63
|
elements.nextBtn.setAttribute('aria-label', 'Go to next page');
|
|
76
64
|
elements.prevBtn.setAttribute('aria-label', 'Go to previous page');
|
|
77
65
|
if (elements.counter) {
|
|
78
66
|
elements.counter.setAttribute('aria-live', 'polite');
|
|
79
67
|
elements.counter.setAttribute('aria-label', 'Current page');
|
|
80
68
|
}
|
|
81
|
-
|
|
69
|
+
|
|
70
|
+
// Parse configuration
|
|
82
71
|
const config = elements.controls?.getAttribute('data-hs-config') || '';
|
|
83
|
-
|
|
84
72
|
const configOptions = config.split(', ').map(opt => opt.trim());
|
|
85
73
|
const isInfiniteMode = configOptions.includes('infinite');
|
|
86
|
-
|
|
74
|
+
|
|
87
75
|
const desktopItems = !isInfiniteMode ? (parseInt(config.match(/show-(\d+)(?!-mobile)/)?.[1]) || 6) : 0;
|
|
88
76
|
const mobileItems = !isInfiniteMode ? (parseInt(config.match(/show-(\d+)-mobile/)?.[1]) || desktopItems) : 0;
|
|
89
|
-
|
|
90
|
-
|
|
77
|
+
|
|
91
78
|
// Early exit for infinite mode - disable pagination completely
|
|
92
79
|
if (isInfiniteMode) {
|
|
93
80
|
if (elements.controls) {
|
|
@@ -98,118 +85,101 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
98
85
|
elements.dotsWrap.style.display = 'none';
|
|
99
86
|
elements.dotsWrap.setAttribute('aria-hidden', 'true');
|
|
100
87
|
}
|
|
101
|
-
return;
|
|
88
|
+
return { initialized: false };
|
|
102
89
|
}
|
|
103
90
|
|
|
104
91
|
const isMobileLayout = () => {
|
|
105
|
-
const breakpoint = getComputedStyle(
|
|
92
|
+
const breakpoint = getComputedStyle(list).getPropertyValue('--data-hs-break').trim().replace(/"/g, '');
|
|
106
93
|
return breakpoint === 'mobile';
|
|
107
94
|
};
|
|
108
|
-
|
|
95
|
+
|
|
96
|
+
const allItems = Array.from(list.children);
|
|
109
97
|
const totalItems = allItems.length;
|
|
110
|
-
if (!totalItems) return;
|
|
111
|
-
|
|
112
|
-
const state = {
|
|
98
|
+
if (!totalItems) return null;
|
|
99
|
+
|
|
100
|
+
const state = {
|
|
101
|
+
totalPages: 1,
|
|
102
|
+
currentIndex: 1,
|
|
103
|
+
currentPage: 1,
|
|
104
|
+
isAnimating: false,
|
|
105
|
+
itemsPerPage: desktopItems
|
|
106
|
+
};
|
|
113
107
|
let wrapperChildren = [];
|
|
114
|
-
let dotTemplates = { active: null, inactive: null };
|
|
115
108
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
109
|
+
// Create live region for announcements
|
|
110
|
+
const liveRegion = document.createElement('div');
|
|
111
|
+
liveRegion.className = 'sr-only';
|
|
112
|
+
liveRegion.setAttribute('aria-live', 'assertive');
|
|
113
|
+
liveRegion.setAttribute('aria-atomic', 'true');
|
|
114
|
+
liveRegion.style.cssText = 'position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden;';
|
|
115
|
+
container.appendChild(liveRegion);
|
|
116
|
+
|
|
117
|
+
const updateCounter = () => {
|
|
118
|
+
if (elements.counter) {
|
|
119
|
+
elements.counter.textContent = `${state.currentPage} / ${state.totalPages}`;
|
|
119
120
|
}
|
|
121
|
+
};
|
|
120
122
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
const announcePageChange = () => {
|
|
124
|
+
liveRegion.textContent = `Page ${state.currentPage} of ${state.totalPages}`;
|
|
125
|
+
setTimeout(() => liveRegion.textContent = '', 1000);
|
|
126
|
+
};
|
|
123
127
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
dotTemplates.active = dot.cloneNode(true);
|
|
128
|
-
} else {
|
|
129
|
-
dotTemplates.inactive = dot.cloneNode(true);
|
|
130
|
-
}
|
|
128
|
+
const manageFocus = () => {
|
|
129
|
+
wrapperChildren.forEach((page, index) => {
|
|
130
|
+
page[index === state.currentIndex ? 'removeAttribute' : 'setAttribute']('inert', '');
|
|
131
131
|
});
|
|
132
|
+
};
|
|
132
133
|
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
const updateHeight = () => {
|
|
135
|
+
const targetPage = wrapperChildren[state.currentIndex];
|
|
136
|
+
if (targetPage) wrapper.style.height = targetPage.offsetHeight + 'px';
|
|
137
|
+
};
|
|
135
138
|
|
|
136
|
-
|
|
137
|
-
if (
|
|
138
|
-
elements.dotsWrap.style.display = 'none';
|
|
139
|
-
elements.dotsWrap.setAttribute('aria-hidden', 'true');
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
139
|
+
const initializeDots = () => {
|
|
140
|
+
if (!elements.dotsWrap) return;
|
|
142
141
|
|
|
143
|
-
//
|
|
144
|
-
elements.dotsWrap.
|
|
145
|
-
elements.dotsWrap.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
cleanup.handlers.push({ element: dot, event: 'click', handler: dotClickHandler });
|
|
164
|
-
|
|
165
|
-
// Add keyboard support
|
|
166
|
-
dot.setAttribute('tabindex', '0');
|
|
167
|
-
dot.setAttribute('role', 'button');
|
|
168
|
-
const dotKeydownHandler = (e) => {
|
|
169
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
170
|
-
e.preventDefault();
|
|
171
|
-
const targetPage = parseInt(dot.getAttribute('data-page'));
|
|
172
|
-
navigateToPage(targetPage);
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
dot.addEventListener('keydown', dotKeydownHandler);
|
|
176
|
-
cleanup.handlers.push({ element: dot, event: 'keydown', handler: dotKeydownHandler });
|
|
177
|
-
|
|
178
|
-
elements.dotsWrap.appendChild(dot);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
142
|
+
// Set pagination attributes for dot system
|
|
143
|
+
elements.dotsWrap.setAttribute('data-hs-pagination', '');
|
|
144
|
+
elements.dotsWrap.setAttribute('data-hs-pagination-total', state.totalPages);
|
|
145
|
+
elements.dotsWrap.setAttribute('data-hs-pagination-current', state.currentPage);
|
|
146
|
+
|
|
147
|
+
// Wait for pagination system to initialize dots
|
|
148
|
+
setTimeout(() => {
|
|
149
|
+
// Listen for dot clicks
|
|
150
|
+
const paginationChangeHandler = (e) => {
|
|
151
|
+
if (e.detail && e.detail.page) {
|
|
152
|
+
navigateToPage(e.detail.page);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
elements.dotsWrap.addEventListener('hs-pagination-change', paginationChangeHandler);
|
|
156
|
+
cleanup.handlers.push({
|
|
157
|
+
element: elements.dotsWrap,
|
|
158
|
+
event: 'hs-pagination-change',
|
|
159
|
+
handler: paginationChangeHandler
|
|
160
|
+
});
|
|
161
|
+
}, 50);
|
|
181
162
|
};
|
|
182
163
|
|
|
183
|
-
const
|
|
184
|
-
if (!elements.dotsWrap ||
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
dots.forEach((dot, index) => {
|
|
189
|
-
const pageNumber = index + 1;
|
|
190
|
-
const isActive = pageNumber === state.currentPage;
|
|
191
|
-
|
|
192
|
-
if (isActive) {
|
|
193
|
-
dot.classList.add('is-active');
|
|
194
|
-
dot.setAttribute('aria-current', 'page');
|
|
195
|
-
} else {
|
|
196
|
-
dot.classList.remove('is-active');
|
|
197
|
-
dot.removeAttribute('aria-current');
|
|
198
|
-
}
|
|
199
|
-
});
|
|
164
|
+
const updateDots = () => {
|
|
165
|
+
if (!elements.dotsWrap || !elements.dotsWrap.hsPaginationUpdate) return;
|
|
166
|
+
elements.dotsWrap.setAttribute('data-hs-pagination-current', state.currentPage);
|
|
167
|
+
elements.dotsWrap.hsPaginationUpdate(state.currentPage);
|
|
200
168
|
};
|
|
201
|
-
|
|
169
|
+
|
|
202
170
|
const initializePagination = (forceItemsPerPage = null) => {
|
|
203
171
|
const currentIsMobile = isMobileLayout();
|
|
204
172
|
state.itemsPerPage = forceItemsPerPage || (currentIsMobile ? mobileItems : desktopItems);
|
|
205
173
|
state.totalPages = Math.ceil(totalItems / state.itemsPerPage);
|
|
206
|
-
|
|
174
|
+
|
|
175
|
+
// Clean up previous page lists
|
|
207
176
|
Array.from(wrapper.children).forEach(child => {
|
|
208
|
-
if (child !==
|
|
177
|
+
if (child !== list) wrapper.removeChild(child);
|
|
209
178
|
});
|
|
210
|
-
|
|
211
|
-
allItems.forEach(item =>
|
|
212
|
-
|
|
179
|
+
list.innerHTML = '';
|
|
180
|
+
allItems.forEach(item => list.appendChild(item));
|
|
181
|
+
|
|
182
|
+
// Single page case
|
|
213
183
|
if (state.totalPages <= 1) {
|
|
214
184
|
if (elements.controls) {
|
|
215
185
|
if (elements.controls.contains(document.activeElement)) document.activeElement.blur();
|
|
@@ -221,11 +191,12 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
221
191
|
elements.dotsWrap.setAttribute('aria-hidden', 'true');
|
|
222
192
|
}
|
|
223
193
|
Object.assign(state, { totalPages: 1, currentIndex: 1, currentPage: 1, isAnimating: false });
|
|
224
|
-
wrapper.style.cssText = `transform: translateX(0%); height: ${
|
|
225
|
-
wrapperChildren = [
|
|
194
|
+
wrapper.style.cssText = `transform: translateX(0%); height: ${list.offsetHeight}px;`;
|
|
195
|
+
wrapperChildren = [list];
|
|
226
196
|
return 1;
|
|
227
197
|
}
|
|
228
|
-
|
|
198
|
+
|
|
199
|
+
// Show controls and dots
|
|
229
200
|
if (elements.controls) {
|
|
230
201
|
elements.controls.style.display = '';
|
|
231
202
|
elements.controls.removeAttribute('aria-hidden');
|
|
@@ -234,56 +205,38 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
234
205
|
elements.dotsWrap.style.display = '';
|
|
235
206
|
elements.dotsWrap.removeAttribute('aria-hidden');
|
|
236
207
|
}
|
|
237
|
-
|
|
208
|
+
|
|
209
|
+
// Create page lists
|
|
238
210
|
const pageLists = Array.from({ length: state.totalPages }, (_, page) => {
|
|
239
|
-
const pageList =
|
|
211
|
+
const pageList = list.cloneNode(false);
|
|
240
212
|
const startIndex = page * state.itemsPerPage;
|
|
241
213
|
const endIndex = Math.min(startIndex + state.itemsPerPage, totalItems);
|
|
242
214
|
allItems.slice(startIndex, endIndex).forEach(item => pageList.appendChild(item.cloneNode(true)));
|
|
243
215
|
return pageList;
|
|
244
216
|
});
|
|
245
|
-
|
|
246
|
-
|
|
217
|
+
|
|
218
|
+
// Insert cloned pages for infinite loop
|
|
219
|
+
wrapper.insertBefore(pageLists[pageLists.length - 1].cloneNode(true), list);
|
|
247
220
|
pageLists.slice(1).forEach(page => wrapper.appendChild(page));
|
|
248
221
|
wrapper.appendChild(pageLists[0].cloneNode(true));
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
222
|
+
|
|
223
|
+
// Populate original list with first page
|
|
224
|
+
list.innerHTML = '';
|
|
225
|
+
Array.from(pageLists[0].children).forEach(item => list.appendChild(item));
|
|
226
|
+
|
|
253
227
|
Object.assign(state, { currentIndex: 1, currentPage: 1, isAnimating: false });
|
|
254
228
|
wrapperChildren = Array.from(wrapper.children);
|
|
255
229
|
wrapper.style.transform = 'translateX(-100%)';
|
|
256
|
-
|
|
230
|
+
|
|
257
231
|
updateCounter();
|
|
258
232
|
updateHeight();
|
|
259
233
|
manageFocus();
|
|
260
234
|
initializeDots();
|
|
261
235
|
return state.totalPages;
|
|
262
236
|
};
|
|
263
|
-
|
|
264
|
-
liveRegion.className = 'sr-only';
|
|
265
|
-
liveRegion.setAttribute('aria-live', 'assertive');
|
|
266
|
-
liveRegion.setAttribute('aria-atomic', 'true');
|
|
267
|
-
liveRegion.style.cssText = 'position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden;';
|
|
268
|
-
container.appendChild(liveRegion);
|
|
269
|
-
|
|
270
|
-
const updateCounter = () => elements.counter && (elements.counter.textContent = `${state.currentPage} / ${state.totalPages}`);
|
|
271
|
-
|
|
272
|
-
const announcePageChange = () => {
|
|
273
|
-
liveRegion.textContent = `Page ${state.currentPage} of ${state.totalPages}`;
|
|
274
|
-
setTimeout(() => liveRegion.textContent = '', 1000);
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
const manageFocus = () => wrapperChildren.forEach((page, index) => {
|
|
278
|
-
page[index === state.currentIndex ? 'removeAttribute' : 'setAttribute']('inert', '');
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
const updateHeight = () => {
|
|
282
|
-
const targetPage = wrapperChildren[state.currentIndex];
|
|
283
|
-
if (targetPage) wrapper.style.height = targetPage.offsetHeight + 'px';
|
|
284
|
-
};
|
|
237
|
+
|
|
285
238
|
let currentLayoutIsMobile = isMobileLayout();
|
|
286
|
-
|
|
239
|
+
|
|
287
240
|
const checkLayoutChange = () => {
|
|
288
241
|
const newIsMobile = isMobileLayout();
|
|
289
242
|
if (newIsMobile !== currentLayoutIsMobile) {
|
|
@@ -293,25 +246,25 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
293
246
|
updateHeight();
|
|
294
247
|
}
|
|
295
248
|
};
|
|
296
|
-
|
|
249
|
+
|
|
297
250
|
const resizeObserver = new ResizeObserver(checkLayoutChange);
|
|
298
251
|
resizeObserver.observe(wrapper);
|
|
299
252
|
cleanup.observers.push(resizeObserver);
|
|
253
|
+
|
|
300
254
|
initializePagination();
|
|
301
|
-
|
|
255
|
+
|
|
302
256
|
const navigateToPage = (targetPage) => {
|
|
303
257
|
if (state.isAnimating || state.totalPages <= 1 || targetPage === state.currentPage) return;
|
|
304
258
|
state.isAnimating = true;
|
|
305
|
-
|
|
306
|
-
// For multi-page jumps, we still use the same transition but update the index directly
|
|
259
|
+
|
|
307
260
|
state.currentIndex = targetPage;
|
|
308
261
|
state.currentPage = targetPage;
|
|
309
|
-
|
|
262
|
+
|
|
310
263
|
updateCounter();
|
|
311
264
|
announcePageChange();
|
|
312
265
|
updateHeight();
|
|
313
|
-
|
|
314
|
-
|
|
266
|
+
updateDots();
|
|
267
|
+
|
|
315
268
|
if (isMobileLayout() && elements.controls) {
|
|
316
269
|
setTimeout(() => {
|
|
317
270
|
const controlsBottom = elements.controls.getBoundingClientRect().bottom + window.pageYOffset;
|
|
@@ -320,22 +273,22 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
320
273
|
window.scrollTo({ top: targetScrollPosition, behavior: 'smooth' });
|
|
321
274
|
}, 50);
|
|
322
275
|
}
|
|
323
|
-
|
|
276
|
+
|
|
324
277
|
wrapper.style.transition = 'transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94)';
|
|
325
278
|
wrapper.style.transform = `translateX(${-state.currentIndex * 100}%)`;
|
|
326
|
-
|
|
279
|
+
|
|
327
280
|
const handleTransitionEnd = () => {
|
|
328
281
|
wrapper.removeEventListener('transitionend', handleTransitionEnd);
|
|
329
282
|
wrapper.style.transition = '';
|
|
330
|
-
|
|
283
|
+
|
|
331
284
|
updateCounter();
|
|
332
285
|
announcePageChange();
|
|
333
286
|
updateHeight();
|
|
334
287
|
manageFocus();
|
|
335
|
-
|
|
288
|
+
updateDots();
|
|
336
289
|
state.isAnimating = false;
|
|
337
290
|
};
|
|
338
|
-
|
|
291
|
+
|
|
339
292
|
wrapper.addEventListener('transitionend', handleTransitionEnd);
|
|
340
293
|
};
|
|
341
294
|
|
|
@@ -343,15 +296,15 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
343
296
|
if (state.isAnimating || state.totalPages <= 1) return;
|
|
344
297
|
state.isAnimating = true;
|
|
345
298
|
state.currentIndex += direction;
|
|
346
|
-
|
|
347
|
-
state.currentPage = state.currentIndex > state.totalPages ? 1 :
|
|
348
|
-
|
|
349
|
-
|
|
299
|
+
|
|
300
|
+
state.currentPage = state.currentIndex > state.totalPages ? 1 :
|
|
301
|
+
state.currentIndex < 1 ? state.totalPages : state.currentIndex;
|
|
302
|
+
|
|
350
303
|
updateCounter();
|
|
351
304
|
announcePageChange();
|
|
352
305
|
updateHeight();
|
|
353
|
-
|
|
354
|
-
|
|
306
|
+
updateDots();
|
|
307
|
+
|
|
355
308
|
if (isMobileLayout() && elements.controls) {
|
|
356
309
|
setTimeout(() => {
|
|
357
310
|
const controlsBottom = elements.controls.getBoundingClientRect().bottom + window.pageYOffset;
|
|
@@ -360,14 +313,14 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
360
313
|
window.scrollTo({ top: targetScrollPosition, behavior: 'smooth' });
|
|
361
314
|
}, 50);
|
|
362
315
|
}
|
|
363
|
-
|
|
316
|
+
|
|
364
317
|
wrapper.style.transition = 'transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94)';
|
|
365
318
|
wrapper.style.transform = `translateX(${-state.currentIndex * 100}%)`;
|
|
366
|
-
|
|
319
|
+
|
|
367
320
|
const handleTransitionEnd = () => {
|
|
368
321
|
wrapper.removeEventListener('transitionend', handleTransitionEnd);
|
|
369
322
|
wrapper.style.transition = '';
|
|
370
|
-
|
|
323
|
+
|
|
371
324
|
if (state.currentIndex > state.totalPages) {
|
|
372
325
|
state.currentIndex = 1;
|
|
373
326
|
state.currentPage = 1;
|
|
@@ -377,17 +330,18 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
377
330
|
state.currentPage = state.totalPages;
|
|
378
331
|
wrapper.style.transform = `translateX(${-state.totalPages * 100}%)`;
|
|
379
332
|
}
|
|
380
|
-
|
|
333
|
+
|
|
381
334
|
updateCounter();
|
|
382
335
|
announcePageChange();
|
|
383
336
|
updateHeight();
|
|
384
337
|
manageFocus();
|
|
385
|
-
|
|
338
|
+
updateDots();
|
|
386
339
|
state.isAnimating = false;
|
|
387
340
|
};
|
|
388
|
-
|
|
341
|
+
|
|
389
342
|
wrapper.addEventListener('transitionend', handleTransitionEnd);
|
|
390
343
|
};
|
|
344
|
+
|
|
391
345
|
const nextHandler = () => navigate(1);
|
|
392
346
|
const prevHandler = () => navigate(-1);
|
|
393
347
|
|
|
@@ -398,31 +352,8 @@ const initPaginationInstance = (originalList, container, cleanup) => {
|
|
|
398
352
|
{ element: elements.nextBtn, event: 'click', handler: nextHandler },
|
|
399
353
|
{ element: elements.prevBtn, event: 'click', handler: prevHandler }
|
|
400
354
|
);
|
|
401
|
-
};
|
|
402
355
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
observers: [],
|
|
406
|
-
handlers: []
|
|
407
|
-
};
|
|
408
|
-
|
|
409
|
-
initInfiniteCarousel(cleanup);
|
|
410
|
-
initInfinitePagination(cleanup);
|
|
411
|
-
|
|
412
|
-
return {
|
|
413
|
-
result: "slider initialized",
|
|
414
|
-
destroy: () => {
|
|
415
|
-
// Disconnect all observers
|
|
416
|
-
cleanup.observers.forEach(obs => obs.disconnect());
|
|
417
|
-
cleanup.observers.length = 0;
|
|
418
|
-
|
|
419
|
-
// Remove all event listeners
|
|
420
|
-
cleanup.handlers.forEach(({ element, event, handler }) => {
|
|
421
|
-
element.removeEventListener(event, handler);
|
|
422
|
-
});
|
|
423
|
-
cleanup.handlers.length = 0;
|
|
424
|
-
}
|
|
425
|
-
};
|
|
426
|
-
};
|
|
356
|
+
return { initialized: true };
|
|
357
|
+
}
|
|
427
358
|
|
|
428
|
-
export const version = "1.0.0";
|
|
359
|
+
export const version = "1.0.0";
|
package/index.js
CHANGED
|
@@ -18,7 +18,6 @@ const initializeHsMain = async () => {
|
|
|
18
18
|
|
|
19
19
|
const utilityModules = {
|
|
20
20
|
"data-hs-util-ba": true,
|
|
21
|
-
"data-hs-util-slider": true,
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
const allDataAttributes = { ...animationModules, ...utilityModules };
|
|
@@ -26,7 +25,6 @@ const initializeHsMain = async () => {
|
|
|
26
25
|
const moduleMap = {
|
|
27
26
|
transition: () => import("./autoInit/transition/transition.js"),
|
|
28
27
|
"data-hs-util-ba": () => import("./utils/before-after/before-after.js"),
|
|
29
|
-
"data-hs-util-slider": () => import("./utils/slider/slider.js"),
|
|
30
28
|
"smooth-scroll": () => import("./autoInit/smooth-scroll/smooth-scroll.js"),
|
|
31
29
|
navbar: () => import("./autoInit/navbar/navbar.js"),
|
|
32
30
|
accessibility: () => import("./autoInit/accessibility/accessibility.js"),
|