Skip to content

Commit 51bcf92

Browse files
committed
chore(utils): updated loop util to allow for a specific min value
1 parent 0566e14 commit 51bcf92

File tree

4 files changed

+93
-38
lines changed

4 files changed

+93
-38
lines changed

Diff for: packages/expansion-panel/src/usePanels.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,14 @@ export function usePanels({
318318
return;
319319
}
320320

321-
attemptFocus(loop(currentIndex, panels.length - 1, increment), panels);
321+
attemptFocus(
322+
loop({
323+
value: currentIndex,
324+
max: panels.length - 1,
325+
increment,
326+
}),
327+
panels
328+
);
322329
},
323330
[panels]
324331
);

Diff for: packages/utils/src/__tests__/loop.ts

+31-16
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,48 @@ import { loop } from "../loop";
22

33
describe("loop", () => {
44
it("should increase the number by 1 when the number is less than or equal to the max number", () => {
5-
expect(loop(0, 3, true)).toBe(1);
6-
expect(loop(0, 1, true)).toBe(1);
7-
expect(loop(1, 100, true)).toBe(2);
5+
expect(loop({ value: 0, max: 3, increment: true })).toBe(1);
6+
expect(loop({ value: 0, max: 1, increment: true })).toBe(1);
7+
expect(loop({ value: 1, max: 100, increment: true })).toBe(2);
88
});
99

1010
it("should decrease the number by 1 when the number is greater than 0", () => {
11-
expect(loop(1, 3, false)).toBe(0);
12-
expect(loop(1, 1, false)).toBe(0);
13-
expect(loop(100, 100, false)).toBe(99);
11+
expect(loop({ value: 1, max: 3, increment: false })).toBe(0);
12+
expect(loop({ value: 1, max: 1, increment: false })).toBe(0);
13+
expect(loop({ value: 100, max: 100, increment: false })).toBe(99);
1414
});
1515

1616
it("should correctly loop around to 0 when the number is the max value and incrementing", () => {
17-
expect(loop(100, 100, true)).toBe(0);
18-
expect(loop(1, 1, true)).toBe(0);
19-
expect(loop(20, 20, true)).toBe(0);
17+
expect(loop({ value: 100, max: 100, increment: true })).toBe(0);
18+
expect(loop({ value: 1, max: 1, increment: true })).toBe(0);
19+
expect(loop({ value: 20, max: 20, increment: true })).toBe(0);
2020
});
2121

2222
it("should correctly loop around to the max value when the number is 0 and decrementing", () => {
23-
expect(loop(0, 100, false)).toBe(100);
24-
expect(loop(0, 1, false)).toBe(1);
25-
expect(loop(0, 20, false)).toBe(20);
23+
expect(loop({ value: 0, max: 100, increment: false })).toBe(100);
24+
expect(loop({ value: 0, max: 1, increment: false })).toBe(1);
25+
expect(loop({ value: 0, max: 20, increment: false })).toBe(20);
2626
});
2727

2828
it("should only keep the number between 0 and the max value if the minmax arg is enabled", () => {
29-
expect(loop(-1, 20, true, true)).toBe(0);
30-
expect(loop(-1, 20, false, true)).toBe(0);
31-
expect(loop(100, 20, true, true)).toBe(20);
32-
expect(loop(100, 20, false, true)).toBe(20);
29+
expect(loop({ value: -1, max: 20, increment: true, minmax: true })).toBe(0);
30+
expect(loop({ value: -1, max: 20, increment: false, minmax: true })).toBe(
31+
0
32+
);
33+
expect(loop({ value: 100, max: 20, increment: true, minmax: true })).toBe(
34+
20
35+
);
36+
expect(loop({ value: 100, max: 20, increment: false, minmax: true })).toBe(
37+
20
38+
);
39+
});
40+
41+
it("should allow for a custom min value", () => {
42+
expect(loop({ value: 0, min: 1, max: 10, increment: false })).toBe(10);
43+
expect(loop({ value: 0, min: -10, max: 10, increment: false })).toBe(-1);
44+
expect(loop({ value: -10, min: -10, max: 10, increment: false })).toBe(10);
45+
46+
// defaults to 0
47+
expect(loop({ value: 0, max: 10, increment: false })).toBe(10);
3348
});
3449
});

Diff for: packages/utils/src/loop.ts

+48-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,61 @@
1+
/**
2+
* @since 2.7.0
3+
*/
4+
export interface LoopOptions {
5+
/**
6+
* The current value that should be modified.
7+
*/
8+
value: number;
9+
10+
/**
11+
* An optional `min` value that can be used before looping to the `max` value.
12+
*
13+
* @default 0
14+
*/
15+
min?: number;
16+
17+
/**
18+
* The max number that can be used before looping to the `min` value.
19+
*/
20+
max: number;
21+
22+
/**
23+
* Boolean if the `value` should be incremented or decremented by `1`.
24+
*/
25+
increment: boolean;
26+
27+
/**
28+
* Boolean if the looping should be ignored and only the `min`/`max` options
29+
* should be respected. In other words, the looping behavior will be disabled
30+
* and the `value` must be: `min >= value <= max`
31+
*/
32+
minmax?: boolean;
33+
}
34+
135
/**
236
* A small util that is used to increment or decrement a number until it reaches
337
* the max value or -1. When that happens, it will loop around to 0 or the max
438
* value respectively. This does not work for different increment numbers or any
539
* values below 0 for now.
640
*
741
* @internal
8-
* @param x The number to increment or decrement
9-
* @param max The max number that can be set
10-
* @param increment Boolean if it should be incremented or decremented
11-
* @param minmax Boolean if the loop functionality should be replaced with
12-
* min-max behavior instead of allowing looping
42+
* @param options {@link LoopOptions}
43+
* @since 2.7.0 The `min` option was added and the arguments changed to an
44+
* object
1345
*/
14-
export function loop(
15-
x: number,
16-
max: number,
17-
increment: boolean,
18-
minmax = false
19-
): number {
20-
let next = x + (increment ? 1 : -1);
46+
export function loop({
47+
value,
48+
min = 0,
49+
max,
50+
increment,
51+
minmax = false,
52+
}: LoopOptions): number {
53+
let next = value + (increment ? 1 : -1);
2154
if (minmax) {
22-
next = Math.min(max, Math.max(0, next));
55+
next = Math.min(max, Math.max(min, next));
2356
} else if (next > max) {
24-
next = 0;
25-
} else if (next < 0) {
57+
next = min;
58+
} else if (next < min) {
2659
next = max;
2760
}
2861

Diff for: packages/utils/src/wia-aria/movement/useKeyboardMovement.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,12 @@ export function useKeyboardMovement<
222222
index = lastIndex;
223223
break;
224224
default:
225-
index = loop(
226-
focusedIndex,
227-
lastIndex,
228-
type === "increment",
229-
!loopable
230-
);
225+
index = loop({
226+
value: focusedIndex,
227+
max: lastIndex,
228+
increment: type === "increment",
229+
minmax: !loopable,
230+
});
231231
}
232232

233233
if (index === focusedIndex) {

0 commit comments

Comments
 (0)