Repository: exadel-inc/esl
Pull request #1692 (2023-05-31 08:39:32)

Bugfix/esl carousel dots
The last non-full group is always expanded by slides of the previous group
[Closes:](#1670)



Patch:
diff --git a/src/modules/esl-carousel/core/nav/esl-carousel.nav.utils.ts b/src/modules/esl-carousel/core/nav/esl-carousel.nav.utils.ts
index 46b7469cc..bad66a30c 100644
--- a/src/modules/esl-carousel/core/nav/esl-carousel.nav.utils.ts
+++ b/src/modules/esl-carousel/core/nav/esl-carousel.nav.utils.ts
@@ -35,8 +35,15 @@ export function groupToIndex(group: number, count: number, size: number): number
 /** @returns numeric group index from slide index */
 export function indexToGroup(index: number, count: number, size: number): number {
   const value = normalizeIndex(index, size);
-  if (value > size - count) return Math.ceil(size / count) - 1;
-  return Math.ceil(value / count);
+  const groupCount = Math.ceil(size / count);
+  const firstGroupIndex = value + count >= size ? groupCount - 1 : Math.floor(value / count);
+  const secondGroupIndex = (firstGroupIndex + 1) % groupCount;
+  // candidate groups have common slides
+  const isGroupIntersected = size - count + 1 < value + count && value + count <= size;
+  const commonCount = isGroupIntersected ? groupCount * count - size : 0;
+  const firstGroupCount = Math.min(size, (firstGroupIndex + 1) * count) - value;
+  const secondGroupCount = count - firstGroupCount + commonCount;
+  return (firstGroupCount >= secondGroupCount) ? firstGroupIndex : secondGroupIndex;
 }
 
 export function indexToDirection(index: number, {activeIndex, size, loop}: ESLCarouselState): ESLCarouselDirection | null {


Test patch:
diff --git a/src/modules/esl-carousel/test/nav/esl-carousel.nav-utils.test.ts b/src/modules/esl-carousel/test/nav/esl-carousel.nav-utils.test.ts
index e34a5bee0..11ce29487 100644
--- a/src/modules/esl-carousel/test/nav/esl-carousel.nav-utils.test.ts
+++ b/src/modules/esl-carousel/test/nav/esl-carousel.nav-utils.test.ts
@@ -64,22 +64,94 @@ describe('ESLCarousel: Nav Utils', () => {
   describe('indexToGroup', () => {
     test.each([
       // [index, active count, size, result]
-      [0, {count: 4, size: 5}, 0],
-      [1, {count: 4, size: 5}, 1],
-      [2, {count: 4, size: 5}, 1],
-      [3, {count: 4, size: 5}, 1],
+      [0, {count: 6, size: 15}, 0],
+      [1, {count: 6, size: 15}, 0],
+      [2, {count: 6, size: 15}, 0],
+      [3, {count: 6, size: 15}, 0],
+      [4, {count: 6, size: 15}, 1],
+      [5, {count: 6, size: 15}, 1],
+      [6, {count: 6, size: 15}, 1],
+      [7, {count: 6, size: 15}, 1],
+      [8, {count: 6, size: 15}, 2],
+      [9, {count: 6, size: 15}, 2],
+      [10, {count: 6, size: 15}, 2],
+      [11, {count: 6, size: 15}, 2],
+      [12, {count: 6, size: 15}, 2],
+      [13, {count: 6, size: 15}, 0],
+      [14, {count: 6, size: 15}, 0],
+
+      [0, {count: 3, size: 5}, 0],
+      [1, {count: 3, size: 5}, 0],
+      [2, {count: 3, size: 5}, 1],
+      [3, {count: 3, size: 5}, 1],
+      [4, {count: 3, size: 5}, 0],
+
+      [1, {count: 2, size: 4}, 0],
+      [3, {count: 2, size: 4}, 1],
+
+      [0, {count: 3, size: 4}, 0],
+      [1, {count: 3, size: 4}, 1],
+      [2, {count: 3, size: 4}, 1],
+      [3, {count: 3, size: 4}, 0],
 
-      [0, {count: 3, size: 8}, 0],
-      [1, {count: 3, size: 8}, 1],
       [2, {count: 3, size: 8}, 1],
-      [3, {count: 3, size: 8}, 1],
-      [4, {count: 3, size: 8}, 2],
-      [5, {count: 3, size: 8}, 2],
+      [4, {count: 3, size: 8}, 1],
       [6, {count: 3, size: 8}, 2],
-      [7, {count: 3, size: 8}, 2],
+      [7, {count: 3, size: 8}, 0],
+
+      [1, {count: 2, size: 3}, 1],
+      [2, {count: 2, size: 3}, 1],
+
+      [0, {count: 2, size: 9}, 0],
+      [1, {count: 2, size: 9}, 0],
+      [2, {count: 2, size: 9}, 1],
+      [3, {count: 2, size: 9}, 1],
+      [4, {count: 2, size: 9}, 2],
+      [5, {count: 2, size: 9}, 2],
+      [6, {count: 2, size: 9}, 3],
+      [7, {count: 2, size: 9}, 4],
+      [8, {count: 2, size: 9}, 4],
+
+      [0, {count: 4, size: 9}, 0],
+      [1, {count: 4, size: 9}, 0],
+      [2, {count: 4, size: 9}, 0],
+      [3, {count: 4, size: 9}, 1],
+      [4, {count: 4, size: 9}, 1],
+      [5, {count: 4, size: 9}, 2],
+      [6, {count: 4, size: 9}, 2],
+      [7, {count: 4, size: 9}, 2],
+      [8, {count: 4, size: 9}, 0],
+
+      [0, {count: 5, size: 9}, 0],
+      [1, {count: 5, size: 9}, 0],
+      [2, {count: 5, size: 9}, 0],
+      [3, {count: 5, size: 9}, 1],
+      [4, {count: 5, size: 9}, 1],
+      [5, {count: 5, size: 9}, 1],
+      [6, {count: 5, size: 9}, 1],
+      [7, {count: 5, size: 9}, 0],
+      [8, {count: 5, size: 9}, 0],
+
+      [0, {count: 6, size: 9}, 0],
+      [1, {count: 6, size: 9}, 0],
+      [2, {count: 6, size: 9}, 1],
+      [3, {count: 6, size: 9}, 1],
+      [4, {count: 6, size: 9}, 1],
+      [5, {count: 6, size: 9}, 1],
+      [6, {count: 6, size: 9}, 1],
+      [7, {count: 6, size: 9}, 0],
+      [8, {count: 6, size: 9}, 0],
+
+      [0, {count: 1, size: 9}, 0],
+      [1, {count: 1, size: 9}, 1],
+      [2, {count: 1, size: 9}, 2],
+      [3, {count: 1, size: 9}, 3],
+      [4, {count: 1, size: 9}, 4],
+      [5, {count: 1, size: 9}, 5],
+      [6, {count: 1, size: 9}, 6],
+      [7, {count: 1, size: 9}, 7],
+      [8, {count: 1, size: 9}, 8],
 
-      [3, {count: 3, size: 9}, 1],
-      [6, {count: 3, size: 9}, 2]
     ])(
       '(index = %d, %o) => %d',
       (index: number, {count, size}: {count: number, size: number}, result: number) => expect(indexToGroup(index, count, size)).toBe(result)