@evermade/overflow-slider 4.1.0 → 4.2.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/README.md CHANGED
@@ -300,6 +300,7 @@ All options are optional.
300
300
 
301
301
  ```ts
302
302
  type DotsOptions = {
303
+ type: 'view' | 'slide';
303
304
  texts: {
304
305
  dotDescription: string;
305
306
  },
@@ -561,6 +562,11 @@ Infinite scroll is not supported and likely never will be. It is not accessible
561
562
 
562
563
  ## Changelog
563
564
 
565
+ ### 4.2.0
566
+
567
+ * Add: View mode in DotsPlugin in addition to previous "slide mode"
568
+ * Fix: Remove forgotten console.log from ClassNamesPlugin
569
+
564
570
  ### 4.1.0
565
571
 
566
572
  * Add: ClassNamesPlugin to add classes to visible/partly visible/hidden slides.
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { default as OverflowSlider } from './plugins/core/index.d2.ts';
1
+ export { default as OverflowSlider } from './plugins/core/index.js';
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type ArrowsMovementTypes = 'view' | 'slide';
4
4
  type ArrowsOptions = {
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type AutoplayMovementTypes = 'view' | 'slide';
4
4
  type AutoplayPluginOptions = {
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type ClassnameOptions = {
4
4
  classNames: {
@@ -41,7 +41,6 @@ function ClassNamesPlugin(args) {
41
41
  };
42
42
  const update = () => {
43
43
  const { targetStart, targetEnd } = getTargetBounds();
44
- console.log('targetStart:', targetStart, 'targetEnd:', targetEnd);
45
44
  slider.slides.forEach((slide) => {
46
45
  const slideRect = slide.getBoundingClientRect();
47
46
  const slideLeft = slideRect.left;
@@ -1 +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};
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}})();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 u=l.classNames[c];if(d){const t=l.classNames[d];t!==u&&t&&n.classList.remove(t)}else o.forEach(t=>{t!==u&&n.classList.remove(t)});u&&!n.classList.contains(u)&&n.classList.add(u),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};
@@ -1,10 +1,12 @@
1
- type Slider<O = {}, C = {}, H extends string = string> = {
1
+ import { SliderOptionArgs, SliderPlugin, SliderCallback, SliderOptions, SliderDetails } from './index.d2.ts';
2
+
3
+ declare function OverflowSlider(container: HTMLElement, options?: SliderOptionArgs, plugins?: SliderPlugin[]): {
2
4
  container: HTMLElement;
3
5
  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;
6
+ emit: (name: string) => void;
7
+ moveToDirection: (direction: "prev" | "next") => void;
8
+ moveToSlideInDirection: (direction: "prev" | "next") => void;
9
+ snapToClosestSlide: (direction: "prev" | "next") => void;
8
10
  moveToSlide: (index: number) => void;
9
11
  canMoveToSlide: (index: number) => boolean;
10
12
  getInclusiveScrollWidth: () => number;
@@ -12,65 +14,10 @@ type Slider<O = {}, C = {}, H extends string = string> = {
12
14
  getScrollLeft: () => number;
13
15
  setScrollLeft: (value: number) => void;
14
16
  setActiveSlideIdx: () => void;
15
- on: (name: H | SliderHooks, cb: SliderCallback) => void;
17
+ on: (name: string, cb: SliderCallback) => void;
16
18
  options: SliderOptions;
17
19
  details: SliderDetails;
18
20
  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;
21
+ } | undefined;
75
22
 
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 };
23
+ export { OverflowSlider as default };
@@ -1,12 +1,10 @@
1
- import { SliderOptionArgs, SliderPlugin, SliderCallback, SliderOptions, SliderDetails } from './index.js';
2
-
3
- declare function OverflowSlider(container: HTMLElement, options?: SliderOptionArgs, plugins?: SliderPlugin[]): {
1
+ type Slider<O = {}, C = {}, H extends string = string> = {
4
2
  container: HTMLElement;
5
3
  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;
4
+ emit: (name: H | SliderHooks) => void;
5
+ moveToDirection: (direction: 'prev' | 'next') => void;
6
+ moveToSlideInDirection: (direction: 'prev' | 'next') => void;
7
+ snapToClosestSlide: (direction: 'prev' | 'next') => void;
10
8
  moveToSlide: (index: number) => void;
11
9
  canMoveToSlide: (index: number) => boolean;
12
10
  getInclusiveScrollWidth: () => number;
@@ -14,10 +12,65 @@ declare function OverflowSlider(container: HTMLElement, options?: SliderOptionAr
14
12
  getScrollLeft: () => number;
15
13
  setScrollLeft: (value: number) => void;
16
14
  setActiveSlideIdx: () => void;
17
- on: (name: string, cb: SliderCallback) => void;
15
+ on: (name: H | SliderHooks, cb: SliderCallback) => void;
18
16
  options: SliderOptions;
19
17
  details: SliderDetails;
20
18
  activeSlideIdx: number;
21
- } | undefined;
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;
22
75
 
23
- export { OverflowSlider as default };
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 };
@@ -1,6 +1,7 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type DotsOptions = {
4
+ type: 'view' | 'slide';
4
5
  texts: {
5
6
  dotDescription: string;
6
7
  };
@@ -7,11 +7,12 @@ const DEFAULT_CLASS_NAMES = {
7
7
  };
8
8
  function DotsPlugin(args) {
9
9
  return (slider) => {
10
- var _a, _b;
10
+ var _a, _b, _c;
11
11
  const options = {
12
+ type: (_a = args === null || args === void 0 ? void 0 : args.type) !== null && _a !== void 0 ? _a : 'slide',
12
13
  texts: Object.assign(Object.assign({}, DEFAULT_TEXTS), (args === null || args === void 0 ? void 0 : args.texts) || []),
13
14
  classNames: Object.assign(Object.assign({}, DEFAULT_CLASS_NAMES), (args === null || args === void 0 ? void 0 : args.classNames) || []),
14
- container: (_a = args === null || args === void 0 ? void 0 : args.container) !== null && _a !== void 0 ? _a : null,
15
+ container: (_b = args === null || args === void 0 ? void 0 : args.container) !== null && _b !== void 0 ? _b : null,
15
16
  };
16
17
  const dots = document.createElement('div');
17
18
  dots.classList.add(options.classNames.dotsContainer);
@@ -20,18 +21,18 @@ function DotsPlugin(args) {
20
21
  dots.setAttribute('data-has-content', slider.details.hasOverflow.toString());
21
22
  dots.innerHTML = '';
22
23
  const dotsList = document.createElement('ul');
23
- const pages = slider.details.slideCount;
24
- const currentItem = slider.activeSlideIdx;
25
- if (pages <= 1) {
24
+ const count = options.type === 'view' ? slider.details.amountOfPages : slider.details.slideCount;
25
+ const currentIndex = options.type === 'view' ? slider.details.currentPage : slider.activeSlideIdx;
26
+ if (count <= 1) {
26
27
  return;
27
28
  }
28
- for (let i = 0; i < pages; i++) {
29
+ for (let i = 0; i < count; i++) {
29
30
  const dotListItem = document.createElement('li');
30
31
  const dot = document.createElement('button');
31
32
  dot.setAttribute('type', 'button');
32
33
  dot.setAttribute('class', options.classNames.dotsItem);
33
- dot.setAttribute('aria-label', options.texts.dotDescription.replace('%d', (i + 1).toString()).replace('%d', pages.toString()));
34
- dot.setAttribute('aria-pressed', (i === currentItem).toString());
34
+ dot.setAttribute('aria-label', options.texts.dotDescription.replace('%d', (i + 1).toString()).replace('%d', count.toString()));
35
+ dot.setAttribute('aria-pressed', (i === currentIndex).toString());
35
36
  dot.setAttribute('data-item', (i + 1).toString());
36
37
  dotListItem.appendChild(dot);
37
38
  dotsList.appendChild(dotListItem);
@@ -45,23 +46,23 @@ function DotsPlugin(args) {
45
46
  }
46
47
  const currentItem = parseInt((_a = currentItemItem.getAttribute('data-item')) !== null && _a !== void 0 ? _a : '1');
47
48
  if (e.key === 'ArrowLeft') {
48
- const previousPage = currentItem - 1;
49
- if (previousPage > 0) {
50
- const matchingDot = dots.querySelector(`[data-item="${previousPage}"]`);
49
+ const previousIndex = currentItem - 1;
50
+ if (previousIndex > 0) {
51
+ const matchingDot = dots.querySelector(`[data-item="${previousIndex}"]`);
51
52
  if (matchingDot) {
52
53
  matchingDot.focus();
53
54
  }
54
- activateDot(previousPage);
55
+ activateDot(previousIndex);
55
56
  }
56
57
  }
57
58
  if (e.key === 'ArrowRight') {
58
- const nextPage = currentItem + 1;
59
- if (nextPage <= pages) {
60
- const matchingDot = dots.querySelector(`[data-item="${nextPage}"]`);
59
+ const nextIndex = currentItem + 1;
60
+ if (nextIndex <= count) {
61
+ const matchingDot = dots.querySelector(`[data-item="${nextIndex}"]`);
61
62
  if (matchingDot) {
62
63
  matchingDot.focus();
63
64
  }
64
- activateDot(nextPage);
65
+ activateDot(nextIndex);
65
66
  }
66
67
  }
67
68
  });
@@ -75,19 +76,30 @@ function DotsPlugin(args) {
75
76
  }
76
77
  }
77
78
  };
78
- const activateDot = (item) => {
79
- slider.moveToSlide(item - 1);
79
+ const activateDot = (index) => {
80
+ if (options.type === 'view') {
81
+ const targetPosition = slider.details.containerWidth * (index - 1);
82
+ const scrollLeft = slider.options.rtl ? -targetPosition : targetPosition;
83
+ slider.container.scrollTo({
84
+ left: scrollLeft,
85
+ behavior: slider.options.scrollBehavior
86
+ });
87
+ }
88
+ else {
89
+ slider.moveToSlide(index - 1);
90
+ }
80
91
  };
81
92
  buildDots();
82
93
  if (options.container) {
83
94
  options.container.appendChild(dots);
84
95
  }
85
96
  else {
86
- (_b = slider.container.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(dots, slider.container.nextSibling);
97
+ (_c = slider.container.parentNode) === null || _c === void 0 ? void 0 : _c.insertBefore(dots, slider.container.nextSibling);
87
98
  }
88
99
  slider.on('scrollEnd', buildDots);
89
100
  slider.on('contentsChanged', buildDots);
90
101
  slider.on('containerSizeChanged', buildDots);
102
+ slider.on('detailsChanged', buildDots);
91
103
  };
92
104
  }
93
105
 
@@ -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 i=>{var o,s,a;const r={type:null!==(o=null==n?void 0:n.type)&&void 0!==o?o:"slide",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!==(s=null==n?void 0:n.container)&&void 0!==s?s:null},l=document.createElement("div");l.classList.add(r.classNames.dotsContainer);let d=null;const c=()=>{l.setAttribute("data-has-content",i.details.hasOverflow.toString()),l.innerHTML="";const t=document.createElement("ul"),e="view"===r.type?i.details.amountOfPages:i.details.slideCount,n="view"===r.type?i.details.currentPage:i.activeSlideIdx;if(!(e<=1)){for(let i=0;i<e;i++){const o=document.createElement("li"),s=document.createElement("button");s.setAttribute("type","button"),s.setAttribute("class",r.classNames.dotsItem),s.setAttribute("aria-label",r.texts.dotDescription.replace("%d",(i+1).toString()).replace("%d",e.toString())),s.setAttribute("aria-pressed",(i===n).toString()),s.setAttribute("data-item",(i+1).toString()),o.appendChild(s),t.appendChild(o),s.addEventListener("click",()=>u(i+1)),s.addEventListener("focus",()=>d=i+1),s.addEventListener("keydown",t=>{var n;const i=l.querySelector('[aria-pressed="true"]');if(!i)return;const o=parseInt(null!==(n=i.getAttribute("data-item"))&&void 0!==n?n:"1");if("ArrowLeft"===t.key){const t=o-1;if(t>0){const e=l.querySelector(`[data-item="${t}"]`);e&&e.focus(),u(t)}}if("ArrowRight"===t.key){const t=o+1;if(t<=e){const e=l.querySelector(`[data-item="${t}"]`);e&&e.focus(),u(t)}}})}if(l.appendChild(t),d){const t=l.querySelector(`[data-item="${d}"]`);t&&t.focus()}}},u=t=>{if("view"===r.type){const e=i.details.containerWidth*(t-1),n=i.options.rtl?-e:e;i.container.scrollTo({left:n,behavior:i.options.scrollBehavior})}else i.moveToSlide(t-1)};c(),r.container?r.container.appendChild(l):null===(a=i.container.parentNode)||void 0===a||a.insertBefore(l,i.container.nextSibling),i.on("scrollEnd",c),i.on("contentsChanged",c),i.on("containerSizeChanged",c),i.on("detailsChanged",c)}}export{n as default};
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type DragScrollingOptions = {
4
4
  draggedDistanceThatPreventsClick: number;
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type FadeOptions = {
4
4
  classNames: {
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type FullWidthOptions = {
4
4
  targetWidth?: (slider: Slider) => number;
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type ScrollIndicatorOptions = {
4
4
  classNames: {
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type SkipLinkOptions = {
4
4
  texts: {
@@ -1,4 +1,4 @@
1
- import { DeepPartial, Slider } from '../core/index.js';
1
+ import { DeepPartial, Slider } from '../core/index.d2.ts';
2
2
 
3
3
  type ThumbnailsOptions = {
4
4
  mainSlider: Slider;
@@ -817,6 +817,7 @@ h3:before {
817
817
  .example-container-4-hero {
818
818
  --slider-gap: 0;
819
819
  gap: 0;
820
+ scroll-snap-type: x mandatory;
820
821
  }
821
822
 
822
823
  .example-container-4-hero > * {
@@ -121,6 +121,24 @@ import ClassNamesPlugin from '../dist/plugins/classnames/index.esm.js';
121
121
  );
122
122
  console.log( '1-dots', example1Dots );
123
123
 
124
+ const example1DotsView = new OverflowSlider(
125
+ document.querySelector( '.example-container-1-dots-view' ),
126
+ {
127
+ emulateScrollSnap: true,
128
+ rtl: document.documentElement.dir === 'rtl',
129
+ },
130
+ [
131
+ DragScrollingPlugin(),
132
+ SkipLinksPlugin(),
133
+ DotsPlugin(
134
+ {
135
+ type: 'view',
136
+ }
137
+ ),
138
+ ]
139
+ );
140
+ console.log( '1-dots-view', example1DotsView );
141
+
124
142
  const example1Fade = new OverflowSlider(
125
143
  document.querySelector( '.example-container-1-fade' ),
126
144
  {
@@ -41,7 +41,6 @@ function ClassNamesPlugin(args) {
41
41
  };
42
42
  const update = () => {
43
43
  const { targetStart, targetEnd } = getTargetBounds();
44
- console.log('targetStart:', targetStart, 'targetEnd:', targetEnd);
45
44
  slider.slides.forEach((slide) => {
46
45
  const slideRect = slide.getBoundingClientRect();
47
46
  const slideLeft = slideRect.left;
@@ -1 +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};
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}})();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 u=l.classNames[c];if(d){const t=l.classNames[d];t!==u&&t&&n.classList.remove(t)}else o.forEach(t=>{t!==u&&n.classList.remove(t)});u&&!n.classList.contains(u)&&n.classList.add(u),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};
@@ -1,6 +1,7 @@
1
1
  import { DeepPartial, Slider } from '../core/index.js';
2
2
 
3
3
  type DotsOptions = {
4
+ type: 'view' | 'slide';
4
5
  texts: {
5
6
  dotDescription: string;
6
7
  };
@@ -7,11 +7,12 @@ const DEFAULT_CLASS_NAMES = {
7
7
  };
8
8
  function DotsPlugin(args) {
9
9
  return (slider) => {
10
- var _a, _b;
10
+ var _a, _b, _c;
11
11
  const options = {
12
+ type: (_a = args === null || args === void 0 ? void 0 : args.type) !== null && _a !== void 0 ? _a : 'slide',
12
13
  texts: Object.assign(Object.assign({}, DEFAULT_TEXTS), (args === null || args === void 0 ? void 0 : args.texts) || []),
13
14
  classNames: Object.assign(Object.assign({}, DEFAULT_CLASS_NAMES), (args === null || args === void 0 ? void 0 : args.classNames) || []),
14
- container: (_a = args === null || args === void 0 ? void 0 : args.container) !== null && _a !== void 0 ? _a : null,
15
+ container: (_b = args === null || args === void 0 ? void 0 : args.container) !== null && _b !== void 0 ? _b : null,
15
16
  };
16
17
  const dots = document.createElement('div');
17
18
  dots.classList.add(options.classNames.dotsContainer);
@@ -20,18 +21,18 @@ function DotsPlugin(args) {
20
21
  dots.setAttribute('data-has-content', slider.details.hasOverflow.toString());
21
22
  dots.innerHTML = '';
22
23
  const dotsList = document.createElement('ul');
23
- const pages = slider.details.slideCount;
24
- const currentItem = slider.activeSlideIdx;
25
- if (pages <= 1) {
24
+ const count = options.type === 'view' ? slider.details.amountOfPages : slider.details.slideCount;
25
+ const currentIndex = options.type === 'view' ? slider.details.currentPage : slider.activeSlideIdx;
26
+ if (count <= 1) {
26
27
  return;
27
28
  }
28
- for (let i = 0; i < pages; i++) {
29
+ for (let i = 0; i < count; i++) {
29
30
  const dotListItem = document.createElement('li');
30
31
  const dot = document.createElement('button');
31
32
  dot.setAttribute('type', 'button');
32
33
  dot.setAttribute('class', options.classNames.dotsItem);
33
- dot.setAttribute('aria-label', options.texts.dotDescription.replace('%d', (i + 1).toString()).replace('%d', pages.toString()));
34
- dot.setAttribute('aria-pressed', (i === currentItem).toString());
34
+ dot.setAttribute('aria-label', options.texts.dotDescription.replace('%d', (i + 1).toString()).replace('%d', count.toString()));
35
+ dot.setAttribute('aria-pressed', (i === currentIndex).toString());
35
36
  dot.setAttribute('data-item', (i + 1).toString());
36
37
  dotListItem.appendChild(dot);
37
38
  dotsList.appendChild(dotListItem);
@@ -45,23 +46,23 @@ function DotsPlugin(args) {
45
46
  }
46
47
  const currentItem = parseInt((_a = currentItemItem.getAttribute('data-item')) !== null && _a !== void 0 ? _a : '1');
47
48
  if (e.key === 'ArrowLeft') {
48
- const previousPage = currentItem - 1;
49
- if (previousPage > 0) {
50
- const matchingDot = dots.querySelector(`[data-item="${previousPage}"]`);
49
+ const previousIndex = currentItem - 1;
50
+ if (previousIndex > 0) {
51
+ const matchingDot = dots.querySelector(`[data-item="${previousIndex}"]`);
51
52
  if (matchingDot) {
52
53
  matchingDot.focus();
53
54
  }
54
- activateDot(previousPage);
55
+ activateDot(previousIndex);
55
56
  }
56
57
  }
57
58
  if (e.key === 'ArrowRight') {
58
- const nextPage = currentItem + 1;
59
- if (nextPage <= pages) {
60
- const matchingDot = dots.querySelector(`[data-item="${nextPage}"]`);
59
+ const nextIndex = currentItem + 1;
60
+ if (nextIndex <= count) {
61
+ const matchingDot = dots.querySelector(`[data-item="${nextIndex}"]`);
61
62
  if (matchingDot) {
62
63
  matchingDot.focus();
63
64
  }
64
- activateDot(nextPage);
65
+ activateDot(nextIndex);
65
66
  }
66
67
  }
67
68
  });
@@ -75,19 +76,30 @@ function DotsPlugin(args) {
75
76
  }
76
77
  }
77
78
  };
78
- const activateDot = (item) => {
79
- slider.moveToSlide(item - 1);
79
+ const activateDot = (index) => {
80
+ if (options.type === 'view') {
81
+ const targetPosition = slider.details.containerWidth * (index - 1);
82
+ const scrollLeft = slider.options.rtl ? -targetPosition : targetPosition;
83
+ slider.container.scrollTo({
84
+ left: scrollLeft,
85
+ behavior: slider.options.scrollBehavior
86
+ });
87
+ }
88
+ else {
89
+ slider.moveToSlide(index - 1);
90
+ }
80
91
  };
81
92
  buildDots();
82
93
  if (options.container) {
83
94
  options.container.appendChild(dots);
84
95
  }
85
96
  else {
86
- (_b = slider.container.parentNode) === null || _b === void 0 ? void 0 : _b.insertBefore(dots, slider.container.nextSibling);
97
+ (_c = slider.container.parentNode) === null || _c === void 0 ? void 0 : _c.insertBefore(dots, slider.container.nextSibling);
87
98
  }
88
99
  slider.on('scrollEnd', buildDots);
89
100
  slider.on('contentsChanged', buildDots);
90
101
  slider.on('containerSizeChanged', buildDots);
102
+ slider.on('detailsChanged', buildDots);
91
103
  };
92
104
  }
93
105
 
@@ -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 i=>{var o,s,a;const r={type:null!==(o=null==n?void 0:n.type)&&void 0!==o?o:"slide",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!==(s=null==n?void 0:n.container)&&void 0!==s?s:null},l=document.createElement("div");l.classList.add(r.classNames.dotsContainer);let d=null;const c=()=>{l.setAttribute("data-has-content",i.details.hasOverflow.toString()),l.innerHTML="";const t=document.createElement("ul"),e="view"===r.type?i.details.amountOfPages:i.details.slideCount,n="view"===r.type?i.details.currentPage:i.activeSlideIdx;if(!(e<=1)){for(let i=0;i<e;i++){const o=document.createElement("li"),s=document.createElement("button");s.setAttribute("type","button"),s.setAttribute("class",r.classNames.dotsItem),s.setAttribute("aria-label",r.texts.dotDescription.replace("%d",(i+1).toString()).replace("%d",e.toString())),s.setAttribute("aria-pressed",(i===n).toString()),s.setAttribute("data-item",(i+1).toString()),o.appendChild(s),t.appendChild(o),s.addEventListener("click",()=>u(i+1)),s.addEventListener("focus",()=>d=i+1),s.addEventListener("keydown",t=>{var n;const i=l.querySelector('[aria-pressed="true"]');if(!i)return;const o=parseInt(null!==(n=i.getAttribute("data-item"))&&void 0!==n?n:"1");if("ArrowLeft"===t.key){const t=o-1;if(t>0){const e=l.querySelector(`[data-item="${t}"]`);e&&e.focus(),u(t)}}if("ArrowRight"===t.key){const t=o+1;if(t<=e){const e=l.querySelector(`[data-item="${t}"]`);e&&e.focus(),u(t)}}})}if(l.appendChild(t),d){const t=l.querySelector(`[data-item="${d}"]`);t&&t.focus()}}},u=t=>{if("view"===r.type){const e=i.details.containerWidth*(t-1),n=i.options.rtl?-e:e;i.container.scrollTo({left:n,behavior:i.options.scrollBehavior})}else i.moveToSlide(t-1)};c(),r.container?r.container.appendChild(l):null===(a=i.container.parentNode)||void 0===a||a.insertBefore(l,i.container.nextSibling),i.on("scrollEnd",c),i.on("contentsChanged",c),i.on("containerSizeChanged",c),i.on("detailsChanged",c)}}export{n as default};
package/docs/index.html CHANGED
@@ -158,7 +158,7 @@
158
158
 
159
159
  <div class="entry__item">
160
160
  <h3>Dots</h3>
161
- <p>Display dots indicator. Uses DotsPlugin.</p>
161
+ <p>Display dots indicator (by slide). Uses DotsPlugin.</p>
162
162
  <div class="overflow-slider example-container example-container-1-dots">
163
163
  <a href="#1" class="example-item example-item--1">1</a>
164
164
  <a href="#2" class="example-item example-item--2">2</a>
@@ -167,6 +167,19 @@
167
167
  <a href="#5" class="example-item example-item--5">5</a>
168
168
  <a href="#6" class="example-item example-item--6">6</a>
169
169
  </div>
170
+ <p style="margin-top:1.5rem;">Display dots indicator (by view).</p>
171
+ <div class="overflow-slider example-container example-container-1-dots-view">
172
+ <a href="#1" class="example-item example-item--1">1</a>
173
+ <a href="#2" class="example-item example-item--2">2</a>
174
+ <a href="#3" class="example-item example-item--3">3</a>
175
+ <a href="#4" class="example-item example-item--4">4</a>
176
+ <a href="#5" class="example-item example-item--5">5</a>
177
+ <a href="#6" class="example-item example-item--6">6</a>
178
+ <a href="#7" class="example-item example-item--7">7</a>
179
+ <a href="#8" class="example-item example-item--8">8</a>
180
+ <a href="#9" class="example-item example-item--9">9</a>
181
+ <a href="#10" class="example-item example-item--10">10</a>
182
+ </div>
170
183
  </div>
171
184
 
172
185
  <div class="entry__item">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evermade/overflow-slider",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "Accessible slider that is powered by overflow: auto.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -70,8 +70,6 @@ export default function ClassNamesPlugin( args?: DeepPartial<ClassnameOptions> )
70
70
  const update = () => {
71
71
  const { targetStart, targetEnd } = getTargetBounds();
72
72
 
73
- console.log( 'targetStart:', targetStart, 'targetEnd:', targetEnd );
74
-
75
73
  slider.slides.forEach( ( slide ) => {
76
74
  const slideRect = slide.getBoundingClientRect();
77
75
  const slideLeft = slideRect.left;
@@ -1,6 +1,7 @@
1
1
  import { Slider, DeepPartial } from '../../core/types';
2
2
 
3
3
  export type DotsOptions = {
4
+ type: 'view' | 'slide';
4
5
  texts: {
5
6
  dotDescription: string;
6
7
  },
@@ -23,6 +24,7 @@ const DEFAULT_CLASS_NAMES = {
23
24
  export default function DotsPlugin( args?: DeepPartial<DotsOptions> ) {
24
25
  return ( slider: Slider ) => {
25
26
  const options = <DotsOptions>{
27
+ type: args?.type ?? 'slide',
26
28
  texts: {
27
29
  ...DEFAULT_TEXTS,
28
30
  ...args?.texts || []
@@ -45,20 +47,20 @@ export default function DotsPlugin( args?: DeepPartial<DotsOptions> ) {
45
47
 
46
48
  const dotsList = document.createElement( 'ul' );
47
49
 
48
- const pages = slider.details.slideCount;
49
- const currentItem = slider.activeSlideIdx;
50
+ const count = options.type === 'view' ? slider.details.amountOfPages : slider.details.slideCount;
51
+ const currentIndex = options.type === 'view' ? slider.details.currentPage : slider.activeSlideIdx;
50
52
 
51
- if ( pages <= 1 ) {
53
+ if ( count <= 1 ) {
52
54
  return;
53
55
  }
54
56
 
55
- for ( let i = 0; i < pages; i++ ) {
57
+ for ( let i = 0; i < count; i++ ) {
56
58
  const dotListItem = document.createElement( 'li' );
57
59
  const dot = document.createElement( 'button' );
58
60
  dot.setAttribute( 'type', 'button' );
59
61
  dot.setAttribute( 'class', options.classNames.dotsItem );
60
- dot.setAttribute( 'aria-label', options.texts.dotDescription.replace( '%d', ( i + 1 ).toString() ).replace( '%d', pages.toString() ) );
61
- dot.setAttribute( 'aria-pressed', ( i === currentItem ).toString() );
62
+ dot.setAttribute( 'aria-label', options.texts.dotDescription.replace( '%d', ( i + 1 ).toString() ).replace( '%d', count.toString() ) );
63
+ dot.setAttribute( 'aria-pressed', ( i === currentIndex ).toString() );
62
64
  dot.setAttribute( 'data-item', ( i + 1 ).toString() );
63
65
  dotListItem.appendChild( dot );
64
66
  dotsList.appendChild( dotListItem );
@@ -71,23 +73,23 @@ export default function DotsPlugin( args?: DeepPartial<DotsOptions> ) {
71
73
  }
72
74
  const currentItem = parseInt( currentItemItem.getAttribute( 'data-item' ) ?? '1' );
73
75
  if ( e.key === 'ArrowLeft' ) {
74
- const previousPage = currentItem - 1;
75
- if ( previousPage > 0 ) {
76
- const matchingDot = dots.querySelector( `[data-item="${previousPage}"]` );
76
+ const previousIndex = currentItem - 1;
77
+ if ( previousIndex > 0 ) {
78
+ const matchingDot = dots.querySelector( `[data-item="${previousIndex}"]` );
77
79
  if ( matchingDot ) {
78
80
  ( <HTMLElement>matchingDot ).focus();
79
81
  }
80
- activateDot( previousPage );
82
+ activateDot( previousIndex );
81
83
  }
82
84
  }
83
85
  if ( e.key === 'ArrowRight' ) {
84
- const nextPage = currentItem + 1;
85
- if ( nextPage <= pages ) {
86
- const matchingDot = dots.querySelector( `[data-item="${nextPage}"]` );
86
+ const nextIndex = currentItem + 1;
87
+ if ( nextIndex <= count ) {
88
+ const matchingDot = dots.querySelector( `[data-item="${nextIndex}"]` );
87
89
  if ( matchingDot ) {
88
90
  ( <HTMLElement>matchingDot ).focus();
89
91
  }
90
- activateDot( nextPage );
92
+ activateDot( nextIndex );
91
93
  }
92
94
  }
93
95
  } );
@@ -104,8 +106,17 @@ export default function DotsPlugin( args?: DeepPartial<DotsOptions> ) {
104
106
  }
105
107
  };
106
108
 
107
- const activateDot = ( item: number ) => {
108
- slider.moveToSlide( item - 1 );
109
+ const activateDot = ( index: number ) => {
110
+ if ( options.type === 'view' ) {
111
+ const targetPosition = slider.details.containerWidth * ( index - 1 );
112
+ const scrollLeft = slider.options.rtl ? -targetPosition : targetPosition;
113
+ slider.container.scrollTo({
114
+ left: scrollLeft,
115
+ behavior: slider.options.scrollBehavior as ScrollBehavior
116
+ });
117
+ } else {
118
+ slider.moveToSlide( index - 1 );
119
+ }
109
120
  };
110
121
 
111
122
  buildDots();
@@ -119,5 +130,6 @@ export default function DotsPlugin( args?: DeepPartial<DotsOptions> ) {
119
130
  slider.on( 'scrollEnd', buildDots );
120
131
  slider.on( 'contentsChanged', buildDots );
121
132
  slider.on( 'containerSizeChanged', buildDots );
133
+ slider.on( 'detailsChanged', buildDots );
122
134
  };
123
135
  };