@evermade/overflow-slider 3.3.1 → 4.1.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.
Files changed (119) hide show
  1. package/.nvmrc +1 -1
  2. package/README.md +158 -33
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.esm.js +645 -1
  5. package/dist/index.esm.js.map +1 -0
  6. package/dist/index.min.js +2 -1
  7. package/dist/index.min.js.map +1 -0
  8. package/dist/mixins.scss +14 -0
  9. package/dist/overflow-slider.css +1 -1
  10. package/dist/plugins/arrows/index.d.ts +26 -0
  11. package/dist/plugins/arrows/index.min.js +1 -1
  12. package/dist/plugins/autoplay/index.d.ts +41 -0
  13. package/dist/plugins/autoplay/index.esm.js +233 -0
  14. package/dist/plugins/autoplay/index.min.js +1 -0
  15. package/dist/plugins/classnames/index.d.ts +14 -0
  16. package/dist/plugins/classnames/index.esm.js +108 -0
  17. package/dist/plugins/classnames/index.min.js +1 -0
  18. package/dist/plugins/core/index.d.ts +76 -0
  19. package/dist/plugins/core/index.d2.ts +23 -0
  20. package/dist/plugins/dots/index.d.ts +16 -0
  21. package/dist/plugins/dots/index.min.js +1 -1
  22. package/dist/plugins/drag-scrolling/index.d.ts +9 -0
  23. package/dist/plugins/drag-scrolling/index.esm.js +2 -2
  24. package/dist/plugins/drag-scrolling/index.min.js +1 -1
  25. package/dist/plugins/fade/index.d.ts +16 -0
  26. package/dist/plugins/fade/index.min.js +1 -1
  27. package/dist/plugins/full-width/index.d.ts +11 -0
  28. package/dist/plugins/full-width/index.esm.js +37 -9
  29. package/dist/plugins/full-width/index.min.js +1 -1
  30. package/dist/plugins/infinite-scroll/index.d.ts +25 -0
  31. package/dist/plugins/infinite-scroll/index.esm.js +75 -0
  32. package/dist/plugins/infinite-scroll/index.min.js +1 -0
  33. package/dist/plugins/scroll-indicator/index.d.ts +14 -0
  34. package/dist/plugins/scroll-indicator/index.esm.js +3 -1
  35. package/dist/plugins/scroll-indicator/index.min.js +1 -1
  36. package/dist/plugins/skip-links/index.d.ts +17 -0
  37. package/dist/plugins/skip-links/index.esm.js +7 -1
  38. package/dist/plugins/skip-links/index.min.js +1 -1
  39. package/dist/plugins/thumbnails/index.d.ts +9 -0
  40. package/dist/plugins/thumbnails/index.min.js +1 -1
  41. package/dist/{core/utils.min.js → utils-Sxwcz8zp.js} +1 -1
  42. package/dist/{core/utils.esm.js → utils-ayDxlweP.js} +1 -1
  43. package/docs/assets/demo.css +156 -0
  44. package/docs/assets/demo.js +92 -8
  45. package/docs/dist/index.d.ts +1 -0
  46. package/docs/dist/index.esm.js +645 -1
  47. package/docs/dist/index.esm.js.map +1 -0
  48. package/docs/dist/index.min.js +2 -1
  49. package/docs/dist/index.min.js.map +1 -0
  50. package/docs/dist/mixins.scss +14 -0
  51. package/docs/dist/overflow-slider.css +1 -1
  52. package/docs/dist/plugins/arrows/index.d.ts +26 -0
  53. package/docs/dist/plugins/arrows/index.min.js +1 -1
  54. package/docs/dist/plugins/autoplay/index.d.ts +41 -0
  55. package/docs/dist/plugins/autoplay/index.esm.js +233 -0
  56. package/docs/dist/plugins/autoplay/index.min.js +1 -0
  57. package/docs/dist/plugins/classnames/index.d.ts +14 -0
  58. package/docs/dist/plugins/classnames/index.esm.js +108 -0
  59. package/docs/dist/plugins/classnames/index.min.js +1 -0
  60. package/docs/dist/plugins/core/index.d.ts +76 -0
  61. package/docs/dist/plugins/core/index.d2.ts +23 -0
  62. package/docs/dist/plugins/dots/index.d.ts +16 -0
  63. package/docs/dist/plugins/dots/index.min.js +1 -1
  64. package/docs/dist/plugins/drag-scrolling/index.d.ts +9 -0
  65. package/docs/dist/plugins/drag-scrolling/index.esm.js +2 -2
  66. package/docs/dist/plugins/drag-scrolling/index.min.js +1 -1
  67. package/docs/dist/plugins/fade/index.d.ts +16 -0
  68. package/docs/dist/plugins/fade/index.min.js +1 -1
  69. package/docs/dist/plugins/full-width/index.d.ts +11 -0
  70. package/docs/dist/plugins/full-width/index.esm.js +37 -9
  71. package/docs/dist/plugins/full-width/index.min.js +1 -1
  72. package/docs/dist/plugins/infinite-scroll/index.d.ts +25 -0
  73. package/docs/dist/plugins/infinite-scroll/index.esm.js +75 -0
  74. package/docs/dist/plugins/infinite-scroll/index.min.js +1 -0
  75. package/docs/dist/plugins/scroll-indicator/index.d.ts +14 -0
  76. package/docs/dist/plugins/scroll-indicator/index.esm.js +3 -1
  77. package/docs/dist/plugins/scroll-indicator/index.min.js +1 -1
  78. package/docs/dist/plugins/skip-links/index.d.ts +17 -0
  79. package/docs/dist/plugins/skip-links/index.esm.js +7 -1
  80. package/docs/dist/plugins/skip-links/index.min.js +1 -1
  81. package/docs/dist/plugins/thumbnails/index.d.ts +9 -0
  82. package/docs/dist/plugins/thumbnails/index.min.js +1 -1
  83. package/docs/dist/{core/utils.min.js → utils-Sxwcz8zp.js} +1 -1
  84. package/docs/dist/{core/utils.esm.js → utils-ayDxlweP.js} +1 -1
  85. package/docs/index-rtl.html +78 -2
  86. package/docs/index.html +86 -1
  87. package/package.json +50 -27
  88. package/rollup.config.js +90 -66
  89. package/src/core/details.ts +4 -0
  90. package/src/core/overflow-slider.ts +4 -2
  91. package/src/core/slider.ts +127 -62
  92. package/src/core/types.ts +30 -1
  93. package/src/mixins.scss +14 -0
  94. package/src/overflow-slider.scss +12 -10
  95. package/src/plugins/arrows/index.ts +2 -2
  96. package/src/plugins/autoplay/index.ts +276 -0
  97. package/src/plugins/autoplay/styles.scss +11 -0
  98. package/src/plugins/classnames/index.ts +147 -0
  99. package/src/plugins/dots/index.ts +2 -2
  100. package/src/plugins/drag-scrolling/index.ts +4 -4
  101. package/src/plugins/fade/index.ts +2 -2
  102. package/src/plugins/full-width/index.ts +43 -11
  103. package/src/plugins/scroll-indicator/index.ts +5 -3
  104. package/src/plugins/skip-links/index.ts +2 -2
  105. package/src/plugins/thumbnails/index.ts +2 -2
  106. package/tsconfig.json +4 -2
  107. package/changelog.md +0 -5
  108. package/dist/core/details.esm.js +0 -35
  109. package/dist/core/details.min.js +0 -1
  110. package/dist/core/overflow-slider.esm.js +0 -29
  111. package/dist/core/overflow-slider.min.js +0 -1
  112. package/dist/core/slider.esm.js +0 -499
  113. package/dist/core/slider.min.js +0 -1
  114. package/docs/dist/core/details.esm.js +0 -35
  115. package/docs/dist/core/details.min.js +0 -1
  116. package/docs/dist/core/overflow-slider.esm.js +0 -29
  117. package/docs/dist/core/overflow-slider.min.js +0 -1
  118. package/docs/dist/core/slider.esm.js +0 -499
  119. package/docs/dist/core/slider.min.js +0 -1
@@ -0,0 +1 @@
1
+ function e(e){return t=>{var n,o,l,a,i,r,s,u,d,c,v,p,m,y,f;const h={delayInMs:null!==(n=null==e?void 0:e.delayInMs)&&void 0!==n?n:5e3,texts:{play:null!==(l=null===(o=null==e?void 0:e.texts)||void 0===o?void 0:o.play)&&void 0!==l?l:"Play",pause:null!==(i=null===(a=null==e?void 0:e.texts)||void 0===a?void 0:a.pause)&&void 0!==i?i:"Pause"},icons:{play:null!==(s=null===(r=null==e?void 0:e.icons)||void 0===r?void 0:r.play)&&void 0!==s?s:'<svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393"/></svg>',pause:null!==(d=null===(u=null==e?void 0:e.icons)||void 0===u?void 0:u.pause)&&void 0!==d?d:'<svg width="16" height="16" fill="currentColor" viewBox="0 0 16 16"><path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5m5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5"/></svg>'},container:null!==(c=null==e?void 0:e.container)&&void 0!==c?c:null,classNames:{autoplayButton:null!==(p=null===(v=null==e?void 0:e.classNames)||void 0===v?void 0:v.autoplayButton)&&void 0!==p?p:"overflow-slider__autoplay"},movementType:null!==(m=null==e?void 0:e.movementType)&&void 0!==m?m:"view",stopOnHover:null===(y=null==e?void 0:e.stopOnHover)||void 0===y||y,loop:null===(f=null==e?void 0:e.loop)||void 0===f||f};let g=null,w=null,I=0,x=!1;if(window.matchMedia("(prefers-reduced-motion: reduce)").matches)return;const M=(()=>{var e;const n=document.createElement("button");n.type="button",n.className=h.classNames.autoplayButton,E(n),n.style.setProperty("--autoplay-delay-progress","0"),h.container?h.container.appendChild(n):null===(e=t.container.parentElement)||void 0===e||e.insertBefore(n,t.container),n.addEventListener("click",()=>{g?(x=!0,C()):(x=!1,T())});const o=["focusin"];h.stopOnHover&&o.push("mouseenter");const l=["focusout"];return h.stopOnHover&&l.push("mouseleave"),o.forEach(e=>t.container.addEventListener(e,()=>{g&&C()})),l.forEach(e=>t.container.addEventListener(e,()=>{g||x||T()})),n})();function b(){if("view"===h.movementType){t.getScrollLeft()+t.getInclusiveClientWidth()>=t.getInclusiveScrollWidth()?h.loop?t.moveToSlide(0):(C(),M.style.setProperty("--autoplay-delay-progress","0")):t.moveToDirection("next")}else{const e=(t.activeSlideIdx+1)%t.details.slideCount;t.canMoveToSlide(e)?t.moveToSlide(e):h.loop?t.moveToSlide(0):(C(),M.style.setProperty("--autoplay-delay-progress","0"))}I=performance.now(),null!==w&&cancelAnimationFrame(w),A()}function A(){const e=performance.now(),t=Math.min((e-I)/h.delayInMs*100,100);M.style.setProperty("--autoplay-delay-progress",`${Math.round(t)}`),t<100&&(w=requestAnimationFrame(A))}function T(){g&&clearInterval(g),w&&cancelAnimationFrame(w),function(e){e.setAttribute("aria-pressed","true"),e.setAttribute("aria-label",h.texts.pause);const t=document.createRange().createContextualFragment(h.icons.pause);e.innerHTML="",e.appendChild(t)}(M),I=performance.now(),A(),g=window.setInterval(b,h.delayInMs)}function C(e=!1){g&&clearInterval(g),w&&cancelAnimationFrame(w),g=w=null,e&&(x=!0),E(M)}function E(e){e.setAttribute("aria-pressed","false"),e.setAttribute("aria-label",h.texts.play);const t=document.createRange().createContextualFragment(h.icons.play);e.innerHTML="",e.appendChild(t),e.style.setProperty("--autoplay-delay-progress","0")}T(),new IntersectionObserver(e=>{for(const t of e)!t.isIntersecting&&g?C():!t.isIntersecting||g||x||T()},{threshold:0}).observe(t.container)}}export{e as default};
@@ -0,0 +1,14 @@
1
+ import { DeepPartial, Slider } from '../core/index.js';
2
+
3
+ type ClassnameOptions = {
4
+ classNames: {
5
+ visible: string;
6
+ partlyVisible: string;
7
+ hidden: string;
8
+ };
9
+ freezeStateOnVisible: boolean;
10
+ };
11
+ declare function ClassNamesPlugin(args?: DeepPartial<ClassnameOptions>): (slider: Slider) => void;
12
+
13
+ export { ClassNamesPlugin as default };
14
+ export type { ClassnameOptions };
@@ -0,0 +1,108 @@
1
+ const DEFAULT_CLASS_NAMES = {
2
+ visible: 'is-visible',
3
+ partlyVisible: 'is-partly-visible',
4
+ hidden: 'is-hidden',
5
+ };
6
+ function ClassNamesPlugin(args) {
7
+ return (slider) => {
8
+ var _a, _b;
9
+ const providedClassNames = (_a = args === null || args === void 0 ? void 0 : args.classNames) !== null && _a !== void 0 ? _a : args === null || args === void 0 ? void 0 : args.classnames;
10
+ const options = {
11
+ classNames: Object.assign(Object.assign({}, DEFAULT_CLASS_NAMES), providedClassNames !== null && providedClassNames !== void 0 ? providedClassNames : {}),
12
+ freezeStateOnVisible: (_b = args === null || args === void 0 ? void 0 : args.freezeStateOnVisible) !== null && _b !== void 0 ? _b : false,
13
+ };
14
+ const slideStates = new WeakMap();
15
+ const uniqueClassNames = Array.from(new Set(Object.values(options.classNames).filter((className) => Boolean(className))));
16
+ const getTargetBounds = () => {
17
+ const sliderRect = slider.container.getBoundingClientRect();
18
+ const sliderWidth = sliderRect.width;
19
+ if (!sliderWidth) {
20
+ return { targetStart: sliderRect.left, targetEnd: sliderRect.right };
21
+ }
22
+ let targetWidth = 0;
23
+ if (typeof slider.options.targetWidth === 'function') {
24
+ try {
25
+ targetWidth = slider.options.targetWidth(slider);
26
+ }
27
+ catch (error) {
28
+ targetWidth = 0;
29
+ }
30
+ }
31
+ if (!Number.isFinite(targetWidth) || targetWidth <= 0) {
32
+ targetWidth = sliderWidth;
33
+ }
34
+ const effectiveTargetWidth = Math.min(targetWidth, sliderWidth);
35
+ const offset = (sliderWidth - effectiveTargetWidth) / 2;
36
+ const clampedOffset = Math.max(offset, 0);
37
+ return {
38
+ targetStart: sliderRect.left + clampedOffset,
39
+ targetEnd: sliderRect.right - clampedOffset,
40
+ };
41
+ };
42
+ const update = () => {
43
+ const { targetStart, targetEnd } = getTargetBounds();
44
+ console.log('targetStart:', targetStart, 'targetEnd:', targetEnd);
45
+ slider.slides.forEach((slide) => {
46
+ const slideRect = slide.getBoundingClientRect();
47
+ const slideLeft = slideRect.left;
48
+ const slideRight = slideRect.right;
49
+ const tolerance = 2;
50
+ const overlapsTarget = (slideRight - tolerance) > targetStart && (slideLeft + tolerance) < targetEnd;
51
+ const fullyInsideTarget = (slideLeft + tolerance) >= targetStart && (slideRight - tolerance) <= targetEnd;
52
+ let nextState = 'hidden';
53
+ if (overlapsTarget) {
54
+ nextState = fullyInsideTarget ? 'visible' : 'partlyVisible';
55
+ }
56
+ const prevState = slideStates.get(slide);
57
+ // If freezeStateOnVisible is enabled and slide was previously visible, keep it frozen
58
+ if (options.freezeStateOnVisible && prevState === 'visible') {
59
+ return;
60
+ }
61
+ if (prevState === nextState) {
62
+ return;
63
+ }
64
+ const nextClass = options.classNames[nextState];
65
+ if (prevState) {
66
+ const prevClass = options.classNames[prevState];
67
+ if (prevClass !== nextClass && prevClass) {
68
+ slide.classList.remove(prevClass);
69
+ }
70
+ }
71
+ else {
72
+ uniqueClassNames.forEach((className) => {
73
+ if (className !== nextClass) {
74
+ slide.classList.remove(className);
75
+ }
76
+ });
77
+ }
78
+ if (nextClass && !slide.classList.contains(nextClass)) {
79
+ slide.classList.add(nextClass);
80
+ }
81
+ slideStates.set(slide, nextState);
82
+ });
83
+ };
84
+ slider.on('created', update);
85
+ slider.on('pluginsLoaded', update);
86
+ slider.on('fullWidthPluginUpdate', update);
87
+ slider.on('contentsChanged', update);
88
+ slider.on('containerSizeChanged', update);
89
+ slider.on('detailsChanged', update);
90
+ slider.on('scrollEnd', update);
91
+ slider.on('scrollStart', update);
92
+ requestAnimationFrame(() => {
93
+ requestAnimationFrame(() => update());
94
+ });
95
+ let requestId = 0;
96
+ const debouncedUpdate = () => {
97
+ if (requestId) {
98
+ window.cancelAnimationFrame(requestId);
99
+ }
100
+ requestId = window.requestAnimationFrame(() => {
101
+ update();
102
+ });
103
+ };
104
+ slider.on('scroll', debouncedUpdate);
105
+ };
106
+ }
107
+
108
+ export { ClassNamesPlugin as default };
@@ -0,0 +1 @@
1
+ const t={visible:"is-visible",partlyVisible:"is-partly-visible",hidden:"is-hidden"};function e(e){return n=>{var i,s;const a=null!==(i=null==e?void 0:e.classNames)&&void 0!==i?i:null==e?void 0:e.classnames,l={classNames:Object.assign(Object.assign({},t),null!=a?a:{}),freezeStateOnVisible:null!==(s=null==e?void 0:e.freezeStateOnVisible)&&void 0!==s&&s},r=new WeakMap,o=Array.from(new Set(Object.values(l.classNames).filter(t=>Boolean(t)))),c=()=>{const{targetStart:t,targetEnd:e}=(()=>{const t=n.container.getBoundingClientRect(),e=t.width;if(!e)return{targetStart:t.left,targetEnd:t.right};let i=0;if("function"==typeof n.options.targetWidth)try{i=n.options.targetWidth(n)}catch(t){i=0}(!Number.isFinite(i)||i<=0)&&(i=e);const s=(e-Math.min(i,e))/2,a=Math.max(s,0);return{targetStart:t.left+a,targetEnd:t.right-a}})();console.log("targetStart:",t,"targetEnd:",e),n.slides.forEach(n=>{const i=n.getBoundingClientRect(),s=i.left,a=i.right;let c="hidden";a-2>t&&s+2<e&&(c=s+2>=t&&a-2<=e?"visible":"partlyVisible");const d=r.get(n);if(l.freezeStateOnVisible&&"visible"===d)return;if(d===c)return;const g=l.classNames[c];if(d){const t=l.classNames[d];t!==g&&t&&n.classList.remove(t)}else o.forEach(t=>{t!==g&&n.classList.remove(t)});g&&!n.classList.contains(g)&&n.classList.add(g),r.set(n,c)})};n.on("created",c),n.on("pluginsLoaded",c),n.on("fullWidthPluginUpdate",c),n.on("contentsChanged",c),n.on("containerSizeChanged",c),n.on("detailsChanged",c),n.on("scrollEnd",c),n.on("scrollStart",c),requestAnimationFrame(()=>{requestAnimationFrame(()=>c())});let d=0;n.on("scroll",()=>{d&&window.cancelAnimationFrame(d),d=window.requestAnimationFrame(()=>{c()})})}}export{e as default};
@@ -0,0 +1,76 @@
1
+ type Slider<O = {}, C = {}, H extends string = string> = {
2
+ container: HTMLElement;
3
+ slides: HTMLElement[];
4
+ emit: (name: H | SliderHooks) => void;
5
+ moveToDirection: (direction: 'prev' | 'next') => void;
6
+ moveToSlideInDirection: (direction: 'prev' | 'next') => void;
7
+ snapToClosestSlide: (direction: 'prev' | 'next') => void;
8
+ moveToSlide: (index: number) => void;
9
+ canMoveToSlide: (index: number) => boolean;
10
+ getInclusiveScrollWidth: () => number;
11
+ getInclusiveClientWidth: () => number;
12
+ getScrollLeft: () => number;
13
+ setScrollLeft: (value: number) => void;
14
+ setActiveSlideIdx: () => void;
15
+ on: (name: H | SliderHooks, cb: SliderCallback) => void;
16
+ options: SliderOptions;
17
+ details: SliderDetails;
18
+ activeSlideIdx: number;
19
+ } & C;
20
+ type SliderCallback<O = {}, C = {}, H extends string = string> = (props: Slider<O, C, H>) => void;
21
+ /**
22
+ * Recursively makes all properties of T optional.
23
+ * @see https://www.typescriptlang.org/docs/handbook/utility-types.html#mapped-types
24
+ */
25
+ type DeepPartial<T> = {
26
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
27
+ };
28
+ type SliderOptions = {
29
+ scrollBehavior: string;
30
+ scrollStrategy: string;
31
+ slidesSelector: string;
32
+ emulateScrollSnap: boolean;
33
+ emulateScrollSnapMaxThreshold?: number;
34
+ cssVariableContainer: HTMLElement;
35
+ rtl: boolean;
36
+ targetWidth?: (slider: Slider) => number;
37
+ [key: string]: unknown;
38
+ };
39
+ type SliderOptionArgs = {
40
+ scrollBehavior?: 'smooth' | 'auto';
41
+ scrollStrategy?: 'fullSlide' | 'partialSlide';
42
+ slidesSelector?: string;
43
+ emulateScrollSnap?: boolean;
44
+ emulateScrollSnapMaxThreshold?: number;
45
+ cssVariableContainer?: HTMLElement;
46
+ rtl?: boolean;
47
+ targetWidth?: (slider: Slider) => number;
48
+ [key: string]: unknown;
49
+ };
50
+ type SliderDetails = {
51
+ hasOverflow: boolean;
52
+ slideCount: number;
53
+ containerWidth: number;
54
+ containerHeight: number;
55
+ scrollableAreaWidth: number;
56
+ amountOfPages: number;
57
+ currentPage: number;
58
+ };
59
+ type SliderHooks = HOOK_CREATED | HOOK_CONTENTS_CHANGED | HOOK_DETAILS_CHANGED | HOOK_CONTAINER_SIZE_CHANGED | HOOK_ACTIVE_SLIDE_CHANGED | HOOK_SCROLL_START | HOOK_SCROLL | HOOK_SCROLL_END | HOOK_NATIVE_SCROLL_START | HOOK_NATIVE_SCROLL | HOOK_NATIVE_SCROLL_END | HOOK_PROGRAMMATIC_SCROLL_START | HOOK_PROGRAMMATIC_SCROLL | HOOK_PROGRAMMATIC_SCROLL_END;
60
+ type HOOK_CREATED = 'created';
61
+ type HOOK_DETAILS_CHANGED = 'detailsChanged';
62
+ type HOOK_CONTENTS_CHANGED = 'contentsChanged';
63
+ type HOOK_CONTAINER_SIZE_CHANGED = 'containerSizeChanged';
64
+ type HOOK_ACTIVE_SLIDE_CHANGED = 'activeSlideChanged';
65
+ type HOOK_SCROLL_START = 'scrollStart';
66
+ type HOOK_SCROLL = 'scroll';
67
+ type HOOK_SCROLL_END = 'scrollEnd';
68
+ type HOOK_NATIVE_SCROLL_START = 'nativeScrollStart';
69
+ type HOOK_NATIVE_SCROLL = 'nativeScroll';
70
+ type HOOK_NATIVE_SCROLL_END = 'nativeScrollEnd';
71
+ type HOOK_PROGRAMMATIC_SCROLL_START = 'programmaticScrollStart';
72
+ type HOOK_PROGRAMMATIC_SCROLL = 'programmaticScroll';
73
+ type HOOK_PROGRAMMATIC_SCROLL_END = 'programmaticScrollEnd';
74
+ type SliderPlugin = (slider: Slider) => void;
75
+
76
+ export type { DeepPartial, HOOK_ACTIVE_SLIDE_CHANGED, HOOK_CONTAINER_SIZE_CHANGED, HOOK_CONTENTS_CHANGED, HOOK_CREATED, HOOK_DETAILS_CHANGED, HOOK_NATIVE_SCROLL, HOOK_NATIVE_SCROLL_END, HOOK_NATIVE_SCROLL_START, HOOK_PROGRAMMATIC_SCROLL, HOOK_PROGRAMMATIC_SCROLL_END, HOOK_PROGRAMMATIC_SCROLL_START, HOOK_SCROLL, HOOK_SCROLL_END, HOOK_SCROLL_START, Slider, SliderCallback, SliderDetails, SliderHooks, SliderOptionArgs, SliderOptions, SliderPlugin };
@@ -0,0 +1,23 @@
1
+ import { SliderOptionArgs, SliderPlugin, SliderCallback, SliderOptions, SliderDetails } from './index.js';
2
+
3
+ declare function OverflowSlider(container: HTMLElement, options?: SliderOptionArgs, plugins?: SliderPlugin[]): {
4
+ container: HTMLElement;
5
+ slides: HTMLElement[];
6
+ emit: (name: string) => void;
7
+ moveToDirection: (direction: "prev" | "next") => void;
8
+ moveToSlideInDirection: (direction: "prev" | "next") => void;
9
+ snapToClosestSlide: (direction: "prev" | "next") => void;
10
+ moveToSlide: (index: number) => void;
11
+ canMoveToSlide: (index: number) => boolean;
12
+ getInclusiveScrollWidth: () => number;
13
+ getInclusiveClientWidth: () => number;
14
+ getScrollLeft: () => number;
15
+ setScrollLeft: (value: number) => void;
16
+ setActiveSlideIdx: () => void;
17
+ on: (name: string, cb: SliderCallback) => void;
18
+ options: SliderOptions;
19
+ details: SliderDetails;
20
+ activeSlideIdx: number;
21
+ } | undefined;
22
+
23
+ export { OverflowSlider as default };
@@ -0,0 +1,16 @@
1
+ import { DeepPartial, Slider } from '../core/index.js';
2
+
3
+ type DotsOptions = {
4
+ texts: {
5
+ dotDescription: string;
6
+ };
7
+ classNames: {
8
+ dotsContainer: string;
9
+ dotsItem: string;
10
+ };
11
+ container: HTMLElement | null;
12
+ };
13
+ declare function DotsPlugin(args?: DeepPartial<DotsOptions>): (slider: Slider) => void;
14
+
15
+ export { DotsPlugin as default };
16
+ export type { DotsOptions };
@@ -1 +1 @@
1
- const t={dotDescription:"Page %d of %d"},e={dotsContainer:"overflow-slider__dots",dotsItem:"overflow-slider__dot-item"};function n(n){return o=>{var i,s;const a={texts:Object.assign(Object.assign({},t),(null==n?void 0:n.texts)||[]),classNames:Object.assign(Object.assign({},e),(null==n?void 0:n.classNames)||[]),container:null!==(i=null==n?void 0:n.container)&&void 0!==i?i:null},r=document.createElement("div");r.classList.add(a.classNames.dotsContainer);let d=null;const l=()=>{r.setAttribute("data-has-content",o.details.hasOverflow.toString()),r.innerHTML="";const t=document.createElement("ul"),e=o.details.slideCount,n=o.activeSlideIdx;if(!(e<=1)){for(let o=0;o<e;o++){const i=document.createElement("li"),s=document.createElement("button");s.setAttribute("type","button"),s.setAttribute("class",a.classNames.dotsItem),s.setAttribute("aria-label",a.texts.dotDescription.replace("%d",(o+1).toString()).replace("%d",e.toString())),s.setAttribute("aria-pressed",(o===n).toString()),s.setAttribute("data-item",(o+1).toString()),i.appendChild(s),t.appendChild(i),s.addEventListener("click",(()=>c(o+1))),s.addEventListener("focus",(()=>d=o+1)),s.addEventListener("keydown",(t=>{var n;const o=r.querySelector('[aria-pressed="true"]');if(!o)return;const i=parseInt(null!==(n=o.getAttribute("data-item"))&&void 0!==n?n:"1");if("ArrowLeft"===t.key){const t=i-1;if(t>0){const e=r.querySelector(`[data-item="${t}"]`);e&&e.focus(),c(t)}}if("ArrowRight"===t.key){const t=i+1;if(t<=e){const e=r.querySelector(`[data-item="${t}"]`);e&&e.focus(),c(t)}}}))}if(r.appendChild(t),d){const t=r.querySelector(`[data-item="${d}"]`);t&&t.focus()}}},c=t=>{o.moveToSlide(t-1)};l(),a.container?a.container.appendChild(r):null===(s=o.container.parentNode)||void 0===s||s.insertBefore(r,o.container.nextSibling),o.on("scrollEnd",l),o.on("contentsChanged",l),o.on("containerSizeChanged",l)}}export{n as default};
1
+ const t={dotDescription:"Page %d of %d"},e={dotsContainer:"overflow-slider__dots",dotsItem:"overflow-slider__dot-item"};function n(n){return o=>{var i,s;const a={texts:Object.assign(Object.assign({},t),(null==n?void 0:n.texts)||[]),classNames:Object.assign(Object.assign({},e),(null==n?void 0:n.classNames)||[]),container:null!==(i=null==n?void 0:n.container)&&void 0!==i?i:null},r=document.createElement("div");r.classList.add(a.classNames.dotsContainer);let d=null;const l=()=>{r.setAttribute("data-has-content",o.details.hasOverflow.toString()),r.innerHTML="";const t=document.createElement("ul"),e=o.details.slideCount,n=o.activeSlideIdx;if(!(e<=1)){for(let o=0;o<e;o++){const i=document.createElement("li"),s=document.createElement("button");s.setAttribute("type","button"),s.setAttribute("class",a.classNames.dotsItem),s.setAttribute("aria-label",a.texts.dotDescription.replace("%d",(o+1).toString()).replace("%d",e.toString())),s.setAttribute("aria-pressed",(o===n).toString()),s.setAttribute("data-item",(o+1).toString()),i.appendChild(s),t.appendChild(i),s.addEventListener("click",()=>c(o+1)),s.addEventListener("focus",()=>d=o+1),s.addEventListener("keydown",t=>{var n;const o=r.querySelector('[aria-pressed="true"]');if(!o)return;const i=parseInt(null!==(n=o.getAttribute("data-item"))&&void 0!==n?n:"1");if("ArrowLeft"===t.key){const t=i-1;if(t>0){const e=r.querySelector(`[data-item="${t}"]`);e&&e.focus(),c(t)}}if("ArrowRight"===t.key){const t=i+1;if(t<=e){const e=r.querySelector(`[data-item="${t}"]`);e&&e.focus(),c(t)}}})}if(r.appendChild(t),d){const t=r.querySelector(`[data-item="${d}"]`);t&&t.focus()}}},c=t=>{o.moveToSlide(t-1)};l(),a.container?a.container.appendChild(r):null===(s=o.container.parentNode)||void 0===s||s.insertBefore(r,o.container.nextSibling),o.on("scrollEnd",l),o.on("contentsChanged",l),o.on("containerSizeChanged",l)}}export{n as default};
@@ -0,0 +1,9 @@
1
+ import { DeepPartial, Slider } from '../core/index.js';
2
+
3
+ type DragScrollingOptions = {
4
+ draggedDistanceThatPreventsClick: number;
5
+ };
6
+ declare function DragScrollingPlugin(args?: DeepPartial<DragScrollingOptions>): (slider: Slider) => void;
7
+
8
+ export { DragScrollingPlugin as default };
9
+ export type { DragScrollingOptions };
@@ -22,7 +22,7 @@ function DragScrollingPlugin(args) {
22
22
  return;
23
23
  }
24
24
  isMouseDown = true;
25
- startX = e.pageX - slider.container.offsetLeft;
25
+ startX = e.pageX - slider.container.getBoundingClientRect().left;
26
26
  scrollLeft = slider.container.scrollLeft;
27
27
  // change cursor to grabbing
28
28
  slider.container.style.cursor = 'grabbing';
@@ -45,7 +45,7 @@ function DragScrollingPlugin(args) {
45
45
  programmaticScrollStarted = true;
46
46
  slider.emit('programmaticScrollStart');
47
47
  }
48
- const x = e.pageX - slider.container.offsetLeft;
48
+ const x = e.pageX - slider.container.getBoundingClientRect().left;
49
49
  const walk = (x - startX);
50
50
  const newScrollLeft = scrollLeft - walk;
51
51
  mayNeedToSnap = true;
@@ -1 +1 @@
1
- function e(e){var t;const o=null!==(t=null==e?void 0:e.draggedDistanceThatPreventsClick)&&void 0!==t?t:20;return e=>{let t=!1,n=0,r=0,a=!1,l=!1,s=!1;e.container.setAttribute("data-has-drag-scrolling","true");if(window.addEventListener("mousedown",(o=>{l=!1,e.details.hasOverflow&&e.container.contains(o.target)&&(t=!0,n=o.pageX-e.container.offsetLeft,r=e.container.scrollLeft,e.container.style.cursor="grabbing",e.container.style.scrollBehavior="auto",o.preventDefault(),o.stopPropagation())})),window.addEventListener("mousemove",(i=>{if(!e.details.hasOverflow)return void(l=!1);if(!t)return void(l=!1);i.preventDefault(),l||(l=!0,e.emit("programmaticScrollStart"));const c=i.pageX-e.container.offsetLeft-n,d=r-c;s=!0,Math.floor(e.container.scrollLeft)!==Math.floor(d)&&(a=e.container.scrollLeft<d),e.container.scrollLeft=d;const f=Math.abs(c),u=e.container.querySelectorAll(e.options.slidesSelector),v=f>o?"none":"";u.forEach((e=>{e.style.pointerEvents=v}))})),window.addEventListener("mouseup",(()=>{e.details.hasOverflow?(t=!1,e.container.style.cursor="",setTimeout((()=>{l=!1,e.container.style.scrollBehavior="";e.container.querySelectorAll(e.options.slidesSelector).forEach((e=>{e.style.pointerEvents=""}))}),50)):l=!1})),e.options.emulateScrollSnap){const o=()=>{s&&!t&&(s=!1,e.snapToClosestSlide(a?"next":"prev"))};e.on("programmaticScrollEnd",o),window.addEventListener("mouseup",o)}}}export{e as default};
1
+ function e(e){var t;const o=null!==(t=null==e?void 0:e.draggedDistanceThatPreventsClick)&&void 0!==t?t:20;return e=>{let t=!1,n=0,r=0,a=!1,l=!1,i=!1;e.container.setAttribute("data-has-drag-scrolling","true");if(window.addEventListener("mousedown",o=>{l=!1,e.details.hasOverflow&&e.container.contains(o.target)&&(t=!0,n=o.pageX-e.container.getBoundingClientRect().left,r=e.container.scrollLeft,e.container.style.cursor="grabbing",e.container.style.scrollBehavior="auto",o.preventDefault(),o.stopPropagation())}),window.addEventListener("mousemove",s=>{if(!e.details.hasOverflow)return void(l=!1);if(!t)return void(l=!1);s.preventDefault(),l||(l=!0,e.emit("programmaticScrollStart"));const c=s.pageX-e.container.getBoundingClientRect().left-n,d=r-c;i=!0,Math.floor(e.container.scrollLeft)!==Math.floor(d)&&(a=e.container.scrollLeft<d),e.container.scrollLeft=d;const u=Math.abs(c),v=e.container.querySelectorAll(e.options.slidesSelector),f=u>o?"none":"";v.forEach(e=>{e.style.pointerEvents=f})}),window.addEventListener("mouseup",()=>{e.details.hasOverflow?(t=!1,e.container.style.cursor="",setTimeout(()=>{l=!1,e.container.style.scrollBehavior="";e.container.querySelectorAll(e.options.slidesSelector).forEach(e=>{e.style.pointerEvents=""})},50)):l=!1}),e.options.emulateScrollSnap){const o=()=>{i&&!t&&(i=!1,e.snapToClosestSlide(a?"next":"prev"))};e.on("programmaticScrollEnd",o),window.addEventListener("mouseup",o)}}}export{e as default};
@@ -0,0 +1,16 @@
1
+ import { DeepPartial, Slider } from '../core/index.js';
2
+
3
+ type FadeOptions = {
4
+ classNames: {
5
+ fadeItem: string;
6
+ fadeItemStart: string;
7
+ fadeItemEnd: string;
8
+ };
9
+ container: HTMLElement | null;
10
+ containerStart: HTMLElement | null;
11
+ containerEnd: HTMLElement | null;
12
+ };
13
+ declare function FadePlugin(args?: DeepPartial<FadeOptions>): (slider: Slider) => void;
14
+
15
+ export { FadePlugin as default };
16
+ export type { FadeOptions };
@@ -1 +1 @@
1
- function t(t){return e=>{var n,a,o;const i={classNames:{fadeItem:"overflow-slider-fade",fadeItemStart:"overflow-slider-fade--start",fadeItemEnd:"overflow-slider-fade--end"},container:null!==(n=null==t?void 0:t.container)&&void 0!==n?n:null,containerStart:null!==(a=null==t?void 0:t.containerStart)&&void 0!==a?a:null,containerEnd:null!==(o=null==t?void 0:t.containerEnd)&&void 0!==o?o:null},l=document.createElement("div");l.classList.add(i.classNames.fadeItem,i.classNames.fadeItemStart),l.setAttribute("aria-hidden","true"),l.setAttribute("tabindex","-1");const r=document.createElement("div");r.classList.add(i.classNames.fadeItem,i.classNames.fadeItemEnd),r.setAttribute("aria-hidden","true"),r.setAttribute("tabindex","-1"),i.containerStart?i.containerStart.appendChild(l):i.container&&i.container.appendChild(l),i.containerEnd?i.containerEnd.appendChild(r):i.container&&i.container.appendChild(r);const d=()=>{l.setAttribute("data-has-fade",(e.getScrollLeft()>l.offsetWidth).toString()),l.style.opacity=(()=>{const t=e.getScrollLeft();return Math.floor(t)<=Math.floor(l.offsetWidth)?t/Math.max(l.offsetWidth,1):1})().toString(),r.setAttribute("data-has-fade",(Math.floor(e.getScrollLeft())<Math.floor(e.getInclusiveScrollWidth()-e.getInclusiveClientWidth()-r.offsetWidth)).toString()),r.style.opacity=(()=>{const t=e.getScrollLeft(),n=e.getInclusiveScrollWidth()-e.getInclusiveClientWidth()-r.offsetWidth;return Math.floor(t)>=Math.floor(n)?(n-t)/Math.max(r.offsetWidth,1)+1:1})().toString()};d(),e.on("created",d),e.on("contentsChanged",d),e.on("containerSizeChanged",d),e.on("scrollEnd",d),e.on("scrollStart",d);let s=0;e.on("scroll",(()=>{s&&window.cancelAnimationFrame(s),s=window.requestAnimationFrame((()=>{d()}))}))}}export{t as default};
1
+ function t(t){return e=>{var n,a,o;const i={classNames:{fadeItem:"overflow-slider-fade",fadeItemStart:"overflow-slider-fade--start",fadeItemEnd:"overflow-slider-fade--end"},container:null!==(n=null==t?void 0:t.container)&&void 0!==n?n:null,containerStart:null!==(a=null==t?void 0:t.containerStart)&&void 0!==a?a:null,containerEnd:null!==(o=null==t?void 0:t.containerEnd)&&void 0!==o?o:null},l=document.createElement("div");l.classList.add(i.classNames.fadeItem,i.classNames.fadeItemStart),l.setAttribute("aria-hidden","true"),l.setAttribute("tabindex","-1");const r=document.createElement("div");r.classList.add(i.classNames.fadeItem,i.classNames.fadeItemEnd),r.setAttribute("aria-hidden","true"),r.setAttribute("tabindex","-1"),i.containerStart?i.containerStart.appendChild(l):i.container&&i.container.appendChild(l),i.containerEnd?i.containerEnd.appendChild(r):i.container&&i.container.appendChild(r);const d=()=>{l.setAttribute("data-has-fade",(e.getScrollLeft()>l.offsetWidth).toString()),l.style.opacity=(()=>{const t=e.getScrollLeft();return Math.floor(t)<=Math.floor(l.offsetWidth)?t/Math.max(l.offsetWidth,1):1})().toString(),r.setAttribute("data-has-fade",(Math.floor(e.getScrollLeft())<Math.floor(e.getInclusiveScrollWidth()-e.getInclusiveClientWidth()-r.offsetWidth)).toString()),r.style.opacity=(()=>{const t=e.getScrollLeft(),n=e.getInclusiveScrollWidth()-e.getInclusiveClientWidth()-r.offsetWidth;return Math.floor(t)>=Math.floor(n)?(n-t)/Math.max(r.offsetWidth,1)+1:1})().toString()};d(),e.on("created",d),e.on("contentsChanged",d),e.on("containerSizeChanged",d),e.on("scrollEnd",d),e.on("scrollStart",d);let s=0;e.on("scroll",()=>{s&&window.cancelAnimationFrame(s),s=window.requestAnimationFrame(()=>{d()})})}}export{t as default};
@@ -0,0 +1,11 @@
1
+ import { DeepPartial, Slider } from '../core/index.js';
2
+
3
+ type FullWidthOptions = {
4
+ targetWidth?: (slider: Slider) => number;
5
+ addMarginBefore: boolean;
6
+ addMarginAfter: boolean;
7
+ };
8
+ declare function FullWidthPlugin(args?: DeepPartial<FullWidthOptions>): (slider: Slider) => void;
9
+
10
+ export { FullWidthPlugin as default };
11
+ export type { FullWidthOptions };
@@ -1,31 +1,59 @@
1
1
  const DEFAULT_TARGET_WIDTH = (slider) => { var _a, _b; return (_b = (_a = slider.container.parentElement) === null || _a === void 0 ? void 0 : _a.offsetWidth) !== null && _b !== void 0 ? _b : window.innerWidth; };
2
2
  function FullWidthPlugin(args) {
3
3
  return (slider) => {
4
- var _a, _b, _c;
4
+ var _a, _b, _c, _d;
5
5
  const options = {
6
- targetWidth: (_a = args === null || args === void 0 ? void 0 : args.targetWidth) !== null && _a !== void 0 ? _a : DEFAULT_TARGET_WIDTH,
6
+ targetWidth: (_a = args === null || args === void 0 ? void 0 : args.targetWidth) !== null && _a !== void 0 ? _a : undefined,
7
7
  addMarginBefore: (_b = args === null || args === void 0 ? void 0 : args.addMarginBefore) !== null && _b !== void 0 ? _b : true,
8
8
  addMarginAfter: (_c = args === null || args === void 0 ? void 0 : args.addMarginAfter) !== null && _c !== void 0 ? _c : true,
9
9
  };
10
+ if (typeof slider.options.targetWidth !== 'function') {
11
+ slider.options.targetWidth = (_d = options.targetWidth) !== null && _d !== void 0 ? _d : DEFAULT_TARGET_WIDTH;
12
+ }
13
+ const resolveTargetWidth = () => {
14
+ var _a;
15
+ if (typeof slider.options.targetWidth === 'function') {
16
+ return slider.options.targetWidth;
17
+ }
18
+ return (_a = options.targetWidth) !== null && _a !== void 0 ? _a : DEFAULT_TARGET_WIDTH;
19
+ };
10
20
  const update = () => {
11
21
  const slides = slider.container.querySelectorAll(slider.options.slidesSelector);
12
22
  if (!slides.length) {
13
23
  return;
14
24
  }
25
+ const targetWidthFn = resolveTargetWidth();
26
+ const rawMargin = (window.innerWidth - targetWidthFn(slider)) / 2;
27
+ const marginAmount = Math.max(0, Math.floor(rawMargin));
28
+ const marginValue = marginAmount ? `${marginAmount}px` : '';
29
+ slides.forEach((slide) => {
30
+ const element = slide;
31
+ element.style.marginInlineStart = '';
32
+ element.style.marginInlineEnd = '';
33
+ });
15
34
  const firstSlide = slides[0];
16
35
  const lastSlide = slides[slides.length - 1];
17
- const marginAmount = Math.floor((window.innerWidth - options.targetWidth(slider)) / 2);
18
36
  if (options.addMarginBefore) {
19
- firstSlide.style.marginInlineStart = `${marginAmount}px`;
37
+ firstSlide.style.marginInlineStart = marginValue;
38
+ slider.container.style.setProperty('scroll-padding-inline-start', marginValue || '0px');
39
+ }
40
+ else {
41
+ slider.container.style.removeProperty('scroll-padding-inline-start');
20
42
  }
21
43
  if (options.addMarginAfter) {
22
- lastSlide.style.marginInlineEnd = `${marginAmount}px`;
44
+ lastSlide.style.marginInlineEnd = marginValue;
45
+ slider.container.style.setProperty('scroll-padding-inline-end', marginValue || '0px');
46
+ }
47
+ else {
48
+ slider.container.style.removeProperty('scroll-padding-inline-end');
23
49
  }
24
- slider.container.setAttribute('data-full-width-offset', marginAmount.toString());
25
- setCSS();
50
+ slider.container.setAttribute('data-full-width-offset', `${marginAmount}`);
51
+ setCSS(targetWidthFn);
52
+ slider.emit('fullWidthPluginUpdate');
26
53
  };
27
- const setCSS = () => {
28
- slider.container.style.setProperty('--slider-container-target-width', `${options.targetWidth(slider)}px`);
54
+ const setCSS = (targetWidthFn) => {
55
+ const width = targetWidthFn(slider);
56
+ slider.options.cssVariableContainer.style.setProperty('--slider-container-target-width', `${width}px`);
29
57
  };
30
58
  update();
31
59
  slider.on('contentsChanged', update);
@@ -1 +1 @@
1
- const t=t=>{var n,e;return null!==(e=null===(n=t.container.parentElement)||void 0===n?void 0:n.offsetWidth)&&void 0!==e?e:window.innerWidth};function n(n){return e=>{var i,r,d;const o={targetWidth:null!==(i=null==n?void 0:n.targetWidth)&&void 0!==i?i:t,addMarginBefore:null===(r=null==n?void 0:n.addMarginBefore)||void 0===r||r,addMarginAfter:null===(d=null==n?void 0:n.addMarginAfter)||void 0===d||d},a=()=>{const t=e.container.querySelectorAll(e.options.slidesSelector);if(!t.length)return;const n=t[0],i=t[t.length-1],r=Math.floor((window.innerWidth-o.targetWidth(e))/2);o.addMarginBefore&&(n.style.marginInlineStart=`${r}px`),o.addMarginAfter&&(i.style.marginInlineEnd=`${r}px`),e.container.setAttribute("data-full-width-offset",r.toString()),l()},l=()=>{e.container.style.setProperty("--slider-container-target-width",`${o.targetWidth(e)}px`)};a(),e.on("contentsChanged",a),e.on("containerSizeChanged",a),window.addEventListener("resize",a)}}export{n as default};
1
+ const t=t=>{var n,e;return null!==(e=null===(n=t.container.parentElement)||void 0===n?void 0:n.offsetWidth)&&void 0!==e?e:window.innerWidth};function n(n){return e=>{var i,r,o,d;const l={targetWidth:null!==(i=null==n?void 0:n.targetWidth)&&void 0!==i?i:void 0,addMarginBefore:null===(r=null==n?void 0:n.addMarginBefore)||void 0===r||r,addMarginAfter:null===(o=null==n?void 0:n.addMarginAfter)||void 0===o||o};"function"!=typeof e.options.targetWidth&&(e.options.targetWidth=null!==(d=l.targetWidth)&&void 0!==d?d:t);const a=()=>{const n=e.container.querySelectorAll(e.options.slidesSelector);if(!n.length)return;const i=(()=>{var n;return"function"==typeof e.options.targetWidth?e.options.targetWidth:null!==(n=l.targetWidth)&&void 0!==n?n:t})(),r=(window.innerWidth-i(e))/2,o=Math.max(0,Math.floor(r)),d=o?`${o}px`:"";n.forEach(t=>{const n=t;n.style.marginInlineStart="",n.style.marginInlineEnd=""});const a=n[0],c=n[n.length-1];l.addMarginBefore?(a.style.marginInlineStart=d,e.container.style.setProperty("scroll-padding-inline-start",d||"0px")):e.container.style.removeProperty("scroll-padding-inline-start"),l.addMarginAfter?(c.style.marginInlineEnd=d,e.container.style.setProperty("scroll-padding-inline-end",d||"0px")):e.container.style.removeProperty("scroll-padding-inline-end"),e.container.setAttribute("data-full-width-offset",`${o}`),s(i),e.emit("fullWidthPluginUpdate")},s=t=>{const n=t(e);e.options.cssVariableContainer.style.setProperty("--slider-container-target-width",`${n}px`)};a(),e.on("contentsChanged",a),e.on("containerSizeChanged",a),window.addEventListener("resize",a)}}export{n as default};
@@ -0,0 +1,25 @@
1
+ import { SliderPlugin } from '../core/index.js';
2
+
3
+ /**
4
+ * Infinite‐scroll plugin
5
+ *
6
+ * Experimental work-in-progress not available for public use yet.
7
+ */
8
+
9
+ /**
10
+ * @typedef {Object} InfiniteScrollOptions
11
+ * @property {number} [lookAheadCount=1] Number of slides to look ahead when deciding to reparent.
12
+ */
13
+ /**
14
+ * Creates an infinite scroll plugin for a slider that re-parents multiple slides
15
+ * before hitting the container edge, to avoid blank space and keep the same
16
+ * active slide visible.
17
+ *
18
+ * @param {InfiniteScrollOptions} [options] Plugin configuration.
19
+ * @returns {SliderPlugin} The configured slider plugin.
20
+ */
21
+ declare function InfiniteScrollPlugin(options?: {
22
+ lookAheadCount?: number;
23
+ }): SliderPlugin;
24
+
25
+ export { InfiniteScrollPlugin as default };
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @typedef {Object} InfiniteScrollOptions
3
+ * @property {number} [lookAheadCount=1] Number of slides to look ahead when deciding to reparent.
4
+ */
5
+ /**
6
+ * Creates an infinite scroll plugin for a slider that re-parents multiple slides
7
+ * before hitting the container edge, to avoid blank space and keep the same
8
+ * active slide visible.
9
+ *
10
+ * @param {InfiniteScrollOptions} [options] Plugin configuration.
11
+ * @returns {SliderPlugin} The configured slider plugin.
12
+ */
13
+ function InfiniteScrollPlugin(options = {}) {
14
+ const { lookAheadCount = 1 } = options;
15
+ return (slider) => {
16
+ const { container, options: sliderOpts } = slider;
17
+ /**
18
+ * Sum widths of the first or last N slides for lookahead.
19
+ *
20
+ * @param {HTMLElement[]} slides List of slide elements.
21
+ * @param {boolean} fromEnd If true, sum last N; otherwise, first N.
22
+ * @returns {number} Total pixel width of N slides.
23
+ */
24
+ function getLookAheadWidth(slides, fromEnd) {
25
+ const slice = fromEnd
26
+ ? slides.slice(-lookAheadCount)
27
+ : slides.slice(0, lookAheadCount);
28
+ return slice.reduce((total, slide) => total + slide.offsetWidth, 0);
29
+ }
30
+ /**
31
+ * Handler for slider.scrollEnd event that re-parents slides
32
+ * and retains the active slide element by recalculating its
33
+ * new index after DOM shifts.
34
+ */
35
+ function onScroll() {
36
+ const activeSlideIdx = slider.activeSlideIdx;
37
+ const scrollLeft = slider.getScrollLeft();
38
+ const viewportWidth = slider.getInclusiveClientWidth();
39
+ const totalWidth = slider.getInclusiveScrollWidth();
40
+ // Grab current slide elements
41
+ let slides = Array.from(container.querySelectorAll(sliderOpts.slidesSelector));
42
+ if (slides.length === 0)
43
+ return;
44
+ // Store reference to currently active slide element
45
+ const activeSlideEl = slides[activeSlideIdx];
46
+ const aheadRight = getLookAheadWidth(slides, false);
47
+ const aheadLeft = getLookAheadWidth(slides, true);
48
+ // 🐆 Tip: Batch DOM reads/writes inside requestAnimationFrame to avoid thrashing.
49
+ if (scrollLeft + viewportWidth >= totalWidth - aheadRight) {
50
+ for (let i = 0; i < lookAheadCount && slides.length; i++) {
51
+ container.append(slides.shift());
52
+ }
53
+ }
54
+ else if (scrollLeft <= aheadLeft) {
55
+ for (let i = 0; i < lookAheadCount && slides.length; i++) {
56
+ container.prepend(slides.pop());
57
+ }
58
+ }
59
+ slider.setActiveSlideIdx();
60
+ // Re-query slides after DOM mutation
61
+ slides = Array.from(container.querySelectorAll(sliderOpts.slidesSelector));
62
+ const newIndex = slides.indexOf(activeSlideEl);
63
+ slides[newIndex];
64
+ if (newIndex >= 0 && slider.canMoveToSlide(newIndex)) {
65
+ slider.moveToSlide(newIndex);
66
+ }
67
+ else {
68
+ slider.snapToClosestSlide('next');
69
+ }
70
+ }
71
+ slider.on('scrollEnd', onScroll);
72
+ };
73
+ }
74
+
75
+ export { InfiniteScrollPlugin as default };
@@ -0,0 +1 @@
1
+ function e(e={}){const{lookAheadCount:t=1}=e;return e=>{const{container:l,options:o}=e;function n(e,l){return(l?e.slice(-t):e.slice(0,t)).reduce((e,t)=>e+t.offsetWidth,0)}e.on("scrollEnd",function(){const i=e.activeSlideIdx,r=e.getScrollLeft(),c=e.getInclusiveClientWidth(),s=e.getInclusiveScrollWidth();let d=Array.from(l.querySelectorAll(o.slidesSelector));if(0===d.length)return;const f=d[i],u=n(d,!1),S=n(d,!0);if(r+c>=s-u)for(let e=0;e<t&&d.length;e++)l.append(d.shift());else if(r<=S)for(let e=0;e<t&&d.length;e++)l.prepend(d.pop());e.setActiveSlideIdx(),d=Array.from(l.querySelectorAll(o.slidesSelector));const a=d.indexOf(f);d[a],a>=0&&e.canMoveToSlide(a)?e.moveToSlide(a):e.snapToClosestSlide("next")})}}export{e as default};
@@ -0,0 +1,14 @@
1
+ import { DeepPartial, Slider } from '../core/index.js';
2
+
3
+ type ScrollIndicatorOptions = {
4
+ classNames: {
5
+ scrollIndicator: string;
6
+ scrollIndicatorBar: string;
7
+ scrollIndicatorButton: string;
8
+ };
9
+ container: HTMLElement | null;
10
+ };
11
+ declare function ScrollIndicatorPlugin(args?: DeepPartial<ScrollIndicatorOptions>): (slider: Slider) => void;
12
+
13
+ export { ScrollIndicatorPlugin as default };
14
+ export type { ScrollIndicatorOptions };
@@ -84,11 +84,13 @@ function ScrollIndicatorPlugin(args) {
84
84
  const scrollbarButtonWidth = scrollbarButton.offsetWidth;
85
85
  const scrollbarButtonLeft = getScrollbarButtonLeftOffset();
86
86
  const scrollbarButtonRight = scrollbarButtonLeft + scrollbarButtonWidth;
87
- const clickX = e.pageX - Math.abs(scrollbarContainer.offsetLeft);
87
+ const clickX = e.pageX - scrollbarContainer.getBoundingClientRect().left;
88
88
  if (Math.floor(clickX) < Math.floor(scrollbarButtonLeft)) {
89
+ console.log('move left');
89
90
  slider.moveToDirection(slider.options.rtl ? 'next' : 'prev');
90
91
  }
91
92
  else if (Math.floor(clickX) > Math.floor(scrollbarButtonRight)) {
93
+ console.log('move right');
92
94
  slider.moveToDirection(slider.options.rtl ? 'prev' : 'next');
93
95
  }
94
96
  });
@@ -1 +1 @@
1
- const t={scrollIndicator:"overflow-slider__scroll-indicator",scrollIndicatorBar:"overflow-slider__scroll-indicator-bar",scrollIndicatorButton:"overflow-slider__scroll-indicator-button"};function e(e){return o=>{var r,n,i;const a={classNames:Object.assign(Object.assign({},t),(null==e?void 0:e.classNames)||[]),container:null!==(r=null==e?void 0:e.container)&&void 0!==r?r:null},s=document.createElement("div");s.setAttribute("class",a.classNames.scrollIndicator),s.setAttribute("tabindex","0"),s.setAttribute("role","scrollbar"),s.setAttribute("aria-controls",null!==(n=o.container.getAttribute("id"))&&void 0!==n?n:""),s.setAttribute("aria-orientation","horizontal"),s.setAttribute("aria-valuemax","100"),s.setAttribute("aria-valuemin","0"),s.setAttribute("aria-valuenow","0");const l=document.createElement("div");l.setAttribute("class",a.classNames.scrollIndicatorBar);const c=document.createElement("div");c.setAttribute("class",a.classNames.scrollIndicatorButton),c.setAttribute("data-is-grabbed","false"),l.appendChild(c),s.appendChild(l);const d=()=>{s.setAttribute("data-has-overflow",o.details.hasOverflow.toString())};d();const u=()=>{const t=c.offsetWidth/o.details.containerWidth,e=o.getScrollLeft()*t;return o.options.rtl?l.offsetWidth-c.offsetWidth-e:e};let f=0;const v=()=>{f&&window.cancelAnimationFrame(f),f=window.requestAnimationFrame((()=>{const t=o.details.containerWidth/o.container.scrollWidth*100,e=u();c.style.width=`${t}%`,c.style.transform=`translateX(${e}px)`;const r=o.getScrollLeft()/(o.getInclusiveScrollWidth()-o.container.offsetWidth)*100;s.setAttribute("aria-valuenow",Math.round(Number.isNaN(r)?0:r).toString())}))};a.container?a.container.appendChild(s):null===(i=o.container.parentNode)||void 0===i||i.insertBefore(s,o.container.nextSibling),v(),o.on("scroll",v),o.on("contentsChanged",v),o.on("containerSizeChanged",v),o.on("detailsChanged",d),s.addEventListener("keydown",(t=>{"ArrowLeft"===t.key?o.moveToDirection("prev"):"ArrowRight"===t.key&&o.moveToDirection("next")}));let b=!1,h=0,m=o.getScrollLeft();s.addEventListener("click",(t=>{if(t.target==c)return;const e=c.offsetWidth,r=u(),n=r+e,i=t.pageX-Math.abs(s.offsetLeft);Math.floor(i)<Math.floor(r)?o.moveToDirection(o.options.rtl?"next":"prev"):Math.floor(i)>Math.floor(n)&&o.moveToDirection(o.options.rtl?"prev":"next")}));const g=t=>{b=!0;const e=t.pageX||t.touches[0].pageX;h=e-s.offsetLeft,m=o.getScrollLeft(),c.style.cursor="grabbing",c.setAttribute("data-is-grabbed","true"),t.preventDefault(),t.stopPropagation()},p=t=>{if(!b)return;t.preventDefault();const e=(t.pageX||t.touches[0].pageX)-s.offsetLeft,r=o.details.scrollableAreaWidth/s.offsetWidth,n=(e-h)*r,i=o.options.rtl?m-n:m+n;o.setScrollLeft(i)},w=()=>{b=!1,c.style.cursor="",c.setAttribute("data-is-grabbed","false")};c.addEventListener("mousedown",g),c.addEventListener("touchstart",g),window.addEventListener("mousemove",p),window.addEventListener("touchmove",p,{passive:!1}),window.addEventListener("mouseup",w),window.addEventListener("touchend",w)}}export{e as default};
1
+ const t={scrollIndicator:"overflow-slider__scroll-indicator",scrollIndicatorBar:"overflow-slider__scroll-indicator-bar",scrollIndicatorButton:"overflow-slider__scroll-indicator-button"};function e(e){return o=>{var n,r,i;const a={classNames:Object.assign(Object.assign({},t),(null==e?void 0:e.classNames)||[]),container:null!==(n=null==e?void 0:e.container)&&void 0!==n?n:null},s=document.createElement("div");s.setAttribute("class",a.classNames.scrollIndicator),s.setAttribute("tabindex","0"),s.setAttribute("role","scrollbar"),s.setAttribute("aria-controls",null!==(r=o.container.getAttribute("id"))&&void 0!==r?r:""),s.setAttribute("aria-orientation","horizontal"),s.setAttribute("aria-valuemax","100"),s.setAttribute("aria-valuemin","0"),s.setAttribute("aria-valuenow","0");const l=document.createElement("div");l.setAttribute("class",a.classNames.scrollIndicatorBar);const c=document.createElement("div");c.setAttribute("class",a.classNames.scrollIndicatorButton),c.setAttribute("data-is-grabbed","false"),l.appendChild(c),s.appendChild(l);const d=()=>{s.setAttribute("data-has-overflow",o.details.hasOverflow.toString())};d();const u=()=>{const t=c.offsetWidth/o.details.containerWidth,e=o.getScrollLeft()*t;return o.options.rtl?l.offsetWidth-c.offsetWidth-e:e};let f=0;const v=()=>{f&&window.cancelAnimationFrame(f),f=window.requestAnimationFrame(()=>{const t=o.details.containerWidth/o.container.scrollWidth*100,e=u();c.style.width=`${t}%`,c.style.transform=`translateX(${e}px)`;const n=o.getScrollLeft()/(o.getInclusiveScrollWidth()-o.container.offsetWidth)*100;s.setAttribute("aria-valuenow",Math.round(Number.isNaN(n)?0:n).toString())})};a.container?a.container.appendChild(s):null===(i=o.container.parentNode)||void 0===i||i.insertBefore(s,o.container.nextSibling),v(),o.on("scroll",v),o.on("contentsChanged",v),o.on("containerSizeChanged",v),o.on("detailsChanged",d),s.addEventListener("keydown",t=>{"ArrowLeft"===t.key?o.moveToDirection("prev"):"ArrowRight"===t.key&&o.moveToDirection("next")});let b=!1,h=0,g=o.getScrollLeft();s.addEventListener("click",t=>{if(t.target==c)return;const e=c.offsetWidth,n=u(),r=n+e,i=t.pageX-s.getBoundingClientRect().left;Math.floor(i)<Math.floor(n)?(console.log("move left"),o.moveToDirection(o.options.rtl?"next":"prev")):Math.floor(i)>Math.floor(r)&&(console.log("move right"),o.moveToDirection(o.options.rtl?"prev":"next"))});const m=t=>{b=!0;const e=t.pageX||t.touches[0].pageX;h=e-s.offsetLeft,g=o.getScrollLeft(),c.style.cursor="grabbing",c.setAttribute("data-is-grabbed","true"),t.preventDefault(),t.stopPropagation()},p=t=>{if(!b)return;t.preventDefault();const e=(t.pageX||t.touches[0].pageX)-s.offsetLeft,n=o.details.scrollableAreaWidth/s.offsetWidth,r=(e-h)*n,i=o.options.rtl?g-r:g+r;o.setScrollLeft(i)},w=()=>{b=!1,c.style.cursor="",c.setAttribute("data-is-grabbed","false")};c.addEventListener("mousedown",m),c.addEventListener("touchstart",m),window.addEventListener("mousemove",p),window.addEventListener("touchmove",p,{passive:!1}),window.addEventListener("mouseup",w),window.addEventListener("touchend",w)}}export{e as default};
@@ -0,0 +1,17 @@
1
+ import { DeepPartial, Slider } from '../core/index.js';
2
+
3
+ type SkipLinkOptions = {
4
+ texts: {
5
+ skipList: string;
6
+ };
7
+ classNames: {
8
+ skipLink: string;
9
+ skipLinkTarget: string;
10
+ };
11
+ containerBefore: HTMLElement | null;
12
+ containerAfter: HTMLElement | null;
13
+ };
14
+ declare function SkipLinksPlugin(args?: DeepPartial<SkipLinkOptions>): (slider: Slider) => void;
15
+
16
+ export { SkipLinksPlugin as default };
17
+ export type { SkipLinkOptions };
@@ -1,4 +1,10 @@
1
- import { generateId } from '../../core/utils.esm.js';
1
+ function generateId(prefix, i = 1) {
2
+ const id = `${prefix}-${i}`;
3
+ if (document.getElementById(id)) {
4
+ return generateId(prefix, i + 1);
5
+ }
6
+ return id;
7
+ }
2
8
 
3
9
  const DEFAULT_TEXTS = {
4
10
  skipList: 'Skip list'
@@ -1 +1 @@
1
- import{generateId as e}from"../../core/utils.min.js";const t={skipList:"Skip list"},n={skipLink:"screen-reader-text",skipLinkTarget:"overflow-slider__skip-link-target"};function i(i){return r=>{var o,s,a,l,c,d;const u={texts:Object.assign(Object.assign({},t),(null==i?void 0:i.texts)||[]),classNames:Object.assign(Object.assign({},n),(null==i?void 0:i.classNames)||[]),containerBefore:null!==(o=null==i?void 0:i.containerAfter)&&void 0!==o?o:null,containerAfter:null!==(s=null==i?void 0:i.containerAfter)&&void 0!==s?s:null},f=e("overflow-slider-skip"),p=document.createElement("a");p.setAttribute("href",`#${f}`),p.textContent=u.texts.skipList,p.classList.add(u.classNames.skipLink);const v=document.createElement("div");v.setAttribute("id",f),v.setAttribute("tabindex","-1"),u.containerBefore?null===(a=u.containerBefore.parentNode)||void 0===a||a.insertBefore(p,u.containerBefore):null===(l=r.container.parentNode)||void 0===l||l.insertBefore(p,r.container),u.containerAfter?null===(c=u.containerAfter.parentNode)||void 0===c||c.insertBefore(v,u.containerAfter.nextSibling):null===(d=r.container.parentNode)||void 0===d||d.insertBefore(v,r.container.nextSibling)}}export{i as default};
1
+ function e(t,n=1){const i=`${t}-${n}`;return document.getElementById(i)?e(t,n+1):i}const t={skipList:"Skip list"},n={skipLink:"screen-reader-text",skipLinkTarget:"overflow-slider__skip-link-target"};function i(i){return r=>{var o,s,a,l,c,d;const u={texts:Object.assign(Object.assign({},t),(null==i?void 0:i.texts)||[]),classNames:Object.assign(Object.assign({},n),(null==i?void 0:i.classNames)||[]),containerBefore:null!==(o=null==i?void 0:i.containerAfter)&&void 0!==o?o:null,containerAfter:null!==(s=null==i?void 0:i.containerAfter)&&void 0!==s?s:null},f=e("overflow-slider-skip"),v=document.createElement("a");v.setAttribute("href",`#${f}`),v.textContent=u.texts.skipList,v.classList.add(u.classNames.skipLink);const p=document.createElement("div");p.setAttribute("id",f),p.setAttribute("tabindex","-1"),u.containerBefore?null===(a=u.containerBefore.parentNode)||void 0===a||a.insertBefore(v,u.containerBefore):null===(l=r.container.parentNode)||void 0===l||l.insertBefore(v,r.container),u.containerAfter?null===(c=u.containerAfter.parentNode)||void 0===c||c.insertBefore(p,u.containerAfter.nextSibling):null===(d=r.container.parentNode)||void 0===d||d.insertBefore(p,r.container.nextSibling)}}export{i as default};