Skip to content

Commit d0820e6

Browse files
committed
chore: rabbit-review
1 parent 0a33457 commit d0820e6

File tree

5 files changed

+54
-48
lines changed

5 files changed

+54
-48
lines changed

src/lib/draggable-list/index.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,8 @@ import { cn } from "../../utils";
1212
import DragAndDropIcon from "../../assets/svgs/drag-and-drop.svg";
1313
import Trash from "../../assets/svgs/trash.svg";
1414
import clsx from "clsx";
15-
import { useList } from "./useList";
15+
import { ListItem, useList } from "./useList";
1616

17-
type ListItem = {
18-
id: string | number;
19-
name: string;
20-
value: any;
21-
};
2217
interface IDraggableList
2318
extends Omit<
2419
ListBoxProps<ListBoxItemProps>,

src/lib/draggable-list/useList.ts

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,15 @@ interface UseListOptions {
1717
export function useList({ initialItems, onChange }: UseListOptions) {
1818
const [items, setItems] = useState<ListItem[]>(initialItems);
1919

20+
// track updates to initialItems
2021
useEffect(() => {
21-
// preventing callback loop, we cannot rely on useEffect dependency since that does not utilize deep comparison
22-
if (_.isEqual(initialItems, items)) return;
23-
24-
setItems(initialItems);
25-
// eslint-disable-next-line react-hooks/exhaustive-deps
22+
setItems((prevItems) => {
23+
// preventing callback loop
24+
if (_.isEqual(initialItems, prevItems)) return prevItems;
25+
return initialItems;
26+
});
2627
}, [initialItems]);
2728

28-
const updateItems = useCallback(
29-
(newItems: ListItem[]) => {
30-
setItems(newItems);
31-
onChange?.(newItems);
32-
},
33-
[onChange],
34-
);
35-
3629
const itemsMap = useMemo(() => {
3730
const map = new Map<Key, ListItem>();
3831
for (const item of items) {
@@ -45,46 +38,59 @@ export function useList({ initialItems, onChange }: UseListOptions) {
4538

4639
const remove = useCallback(
4740
(key: Key) => {
48-
updateItems(items.filter((item) => key !== item.id));
41+
// updateItems(items.filter((item) => key !== item.id));
42+
setItems((prevItems) => {
43+
const newItems = prevItems.filter((item) => key !== item.id);
44+
onChange?.(newItems);
45+
return newItems;
46+
});
4947
},
50-
[items, updateItems],
48+
[onChange],
5149
);
5250

5351
const moveBefore = useCallback(
5452
(targetKey: Key, keys: Iterable<Key>) => {
55-
const key = Array.from(keys)[0];
56-
if (key === targetKey) return;
53+
setItems((prevItems) => {
54+
const key = Array.from(keys)[0];
55+
if (key === targetKey) return prevItems;
56+
57+
const indexFrom = prevItems.findIndex((item) => item.id === key);
58+
const indexTo = prevItems.findIndex((item) => item.id === targetKey);
59+
if (indexFrom === -1 || indexTo === -1) return prevItems;
5760

58-
const indexFrom = items.findIndex((item) => item.id === key);
59-
const indexTo = items.findIndex((item) => item.id === targetKey);
60-
if (indexFrom === -1 || indexTo === -1) return;
61+
const reordered = [...prevItems];
62+
const [movedItem] = reordered.splice(indexFrom, 1);
63+
reordered.splice(indexTo, 0, movedItem);
64+
onChange?.(reordered);
6165

62-
const reordered = [...items];
63-
const [movedItem] = reordered.splice(indexFrom, 1);
64-
reordered.splice(indexTo, 0, movedItem);
65-
updateItems(reordered);
66+
return reordered;
67+
});
6668
},
67-
[items, updateItems],
69+
[onChange],
6870
);
6971

7072
const moveAfter = useCallback(
7173
(targetKey: Key, keys: Iterable<Key>) => {
72-
const key = Array.from(keys)[0];
73-
if (key === targetKey) return;
74+
setItems((prevItems) => {
75+
const key = Array.from(keys)[0];
76+
if (key === targetKey) return prevItems;
7477

75-
const indexFrom = items.findIndex((item) => item.id === key);
76-
const indexTo = items.findIndex((item) => item.id === targetKey);
77-
if (indexFrom === -1 || indexTo === -1) return;
78+
const indexFrom = prevItems.findIndex((item) => item.id === key);
79+
const indexTo = prevItems.findIndex((item) => item.id === targetKey);
80+
if (indexFrom === -1 || indexTo === -1) return prevItems;
7881

79-
const reordered = [...items];
80-
const [movedItem] = reordered.splice(indexFrom, 1);
82+
const reordered = [...prevItems];
83+
const [movedItem] = reordered.splice(indexFrom, 1);
8184

82-
// Adjust if removing item before target index
83-
const insertIndex = indexFrom < indexTo ? indexTo : indexTo + 1;
84-
reordered.splice(insertIndex, 0, movedItem);
85-
updateItems(reordered);
85+
// Adjust if removing item before target index
86+
const insertIndex = indexFrom < indexTo ? indexTo : indexTo + 1;
87+
reordered.splice(insertIndex, 0, movedItem);
88+
onChange?.(reordered);
89+
90+
return reordered;
91+
});
8692
},
87-
[items, updateItems],
93+
[onChange],
8894
);
8995

9096
return {

src/lib/form/bignumber-field/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function BigNumberField({
6464
<>
6565
<Input
6666
{...inputProps}
67-
aria-errormessage="BigNumberFieldError"
67+
aria-errormessage={`BigNumberFieldError-${inputProps.id}`}
6868
name={name}
6969
className={cn(
7070
"hover-short-transition bg-klerosUIComponentsWhiteBackground size-full",
@@ -181,7 +181,7 @@ function BigNumberField({
181181
)}
182182
{props.showFieldError && validationResult.isInvalid && (
183183
<span
184-
id="BigNumberFieldError"
184+
id={`BigNumberFieldError-${inputProps.id}`}
185185
aria-label={validationResult.validationError}
186186
className={cn(
187187
"text-klerosUIComponentsError mt-1 text-sm break-words",

src/lib/form/bignumber-field/useBigNumberField.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ export function useBigNumberField(props: BigNumberFieldProps) {
632632
const validate = props.validate;
633633
if (validate) {
634634
const result = validate(value ?? numberValue);
635-
if (typeof result === `string`) {
635+
if (typeof result === "string") {
636636
fieldErrorProps.isInvalid = true;
637637
fieldErrorProps.validationError = result;
638638
}

src/stories/draggable-list.stories.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { IPreviewArgs } from "./utils";
55

66
import DraggableList from "../lib/draggable-list";
77
import { Button } from "../lib";
8+
import { ListItem } from "../lib/draggable-list/useList";
89

910
const meta = {
1011
component: DraggableList,
@@ -35,7 +36,7 @@ export const Default: Story = {
3536
],
3637
},
3738
render: function Render(args) {
38-
const [items, setItems] = useState([
39+
const [items, setItems] = useState<ListItem[]>([
3940
{ id: 1, name: "Illustrator", value: "" },
4041
{ id: 2, name: "Premiere", value: "" },
4142
{ id: 3, name: "Acrobat", value: "" },
@@ -49,7 +50,11 @@ export const Default: Story = {
4950
};
5051
return (
5152
<div>
52-
<DraggableList {...args} items={items} />
53+
<DraggableList
54+
{...args}
55+
items={items}
56+
updateCallback={(items) => setItems(items)}
57+
/>
5358
<Button onPress={addItem} text="Add Item" className="mt-4" />
5459
</div>
5560
);

0 commit comments

Comments
 (0)