Skip to content

Commit 0c4dbe5

Browse files
committed
[@mantine/hooks]: Add swap handle
1 parent 0cd20b4 commit 0c4dbe5

File tree

3 files changed

+33
-1
lines changed

3 files changed

+33
-1
lines changed

docs/src/pages/hooks/use-list-state.mdx

+7-1
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,17 @@ const apply = () =>
3636
const reorder = () => handlers.reorder({ from: 2, to: 0 });
3737
// values -> [{ a: 4 }, { a: 0 }, { a: 5 }]
3838

39+
// swap items positions
40+
const swap = () => handlers.swap({ from: 0, to: 2 });
41+
// values -> [{ a: 5 }, { a: 0 }, { a: 4 }]
42+
3943
// apply function to each element that matches condition
4044
const applyWhere = () =>
4145
handlers.applyWhere(
4246
(item) => item.a > 0,
4347
(item) => ({ a: item.a + 2 })
4448
);
45-
// values -> [{ a: 6 }, { a: 0 }, { a: 7 }]
49+
// values -> [{ a: 7 }, { a: 0 }, { a: 6 }]
4650

4751
// set entirely new state
4852
const setState = () => handlers.setState([{ a: 6 }, { a: 7 }]);
@@ -75,6 +79,7 @@ The hook provides handlers to work with array data:
7579
- `insert` – insert items at given index
7680
- `remove` – remove items at given indices
7781
- `reorder` – move item from one position to another
82+
- `swap` – swap items positions
7883
- `apply` – apply given function to all items in the list
7984
- `applyWhere` - apply given function to selective items using condition
8085
- `setItem` – replace item at given index
@@ -112,6 +117,7 @@ export interface UseListStateHandlers<T> {
112117
) => void;
113118
remove: (...indices: number[]) => void;
114119
reorder: ({ from, to }: { from: number; to: number }) => void;
120+
swap: ({ from, to }: { from: number; to: number }) => void;
115121
setItem: (index: number, item: T) => void;
116122
setItemProp: <K extends keyof T, U extends T[K]>(
117123
index: number,

packages/@mantine/hooks/src/use-list-state/use-list-state.test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,18 @@ describe('@mantine/hooks/use-list-state', () => {
175175
expect(state).toStrictEqual([TEST_STATE[1], TEST_STATE[2], TEST_STATE[0]]);
176176
});
177177

178+
it('swap items positions with handlers.swap', () => {
179+
const hook = renderHook(() => useListState(TEST_STATE));
180+
181+
act(() => {
182+
const [, handlers] = hook.result.current;
183+
handlers.swap({ from: 0, to: 2 });
184+
});
185+
186+
const [state] = hook.result.current;
187+
expect(state).toStrictEqual([TEST_STATE[2], TEST_STATE[1], TEST_STATE[0]]);
188+
});
189+
178190
it('sets item at given position with handlers.setItem', () => {
179191
const hook = renderHook(() => useListState(TEST_STATE));
180192

packages/@mantine/hooks/src/use-list-state/use-list-state.ts

+14
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface UseListStateHandlers<T> {
1414
) => void;
1515
remove: (...indices: number[]) => void;
1616
reorder: ({ from, to }: { from: number; to: number }) => void;
17+
swap: ({ from, to }: { from: number; to: number }) => void;
1718
setItem: (index: number, item: T) => void;
1819
setItemProp: <K extends keyof T, U extends T[K]>(index: number, prop: K, value: U) => void;
1920
filter: (fn: (item: T, i: number) => boolean) => void;
@@ -61,6 +62,18 @@ export function useListState<T>(initialValue: T[] = []): UseListState<T> {
6162
return cloned;
6263
});
6364

65+
const swap = ({ from, to }: { from: number; to: number }) =>
66+
setState((current) => {
67+
const cloned = [...current];
68+
const fromItem = cloned[from];
69+
const toItem = cloned[to];
70+
71+
cloned.splice(to, 1, fromItem);
72+
cloned.splice(from, 1, toItem);
73+
74+
return cloned;
75+
});
76+
6477
const setItem = (index: number, item: T) =>
6578
setState((current) => {
6679
const cloned = [...current];
@@ -100,6 +113,7 @@ export function useListState<T>(initialValue: T[] = []): UseListState<T> {
100113
applyWhere,
101114
remove,
102115
reorder,
116+
swap,
103117
setItem,
104118
setItemProp,
105119
filter,

0 commit comments

Comments
 (0)