demo-react-animated-list/src/AnimatedListDemo.tsx

140 lines
3.5 KiB
TypeScript
Raw Normal View History

2024-08-06 16:36:00 -07:00
import React, { useReducer } from 'react';
import { useAnimatedListItems } from './useAnimatedListItems';
type Mutation = 'reverse' | 'randomize' | 'insert' | 'remove';
2024-08-06 16:26:30 -07:00
2024-08-06 17:49:02 -07:00
function getRandomChar(): string {
return String.fromCharCode(98 + Math.floor(Math.random() * 25));
}
function getRandomItemName(): string {
return `Serial Number - ${new Array(16)
.fill('')
.map(() => getRandomChar())
.join('')}`;
}
2024-08-06 17:13:43 -07:00
/**
* Randomizer function shamelessly copied unmodified from https://stackoverflow.com/a/12646864
*
* License: https://creativecommons.org/licenses/by-sa/4.0/
*
* Author(s):
* - https://stackoverflow.com/users/310500/laurens-holst
* - https://stackoverflow.com/users/8112776/ashleedawg
*/
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function insertRandomlyIntoArray(array: string[]): string[] {
const insertBefore = Math.floor(Math.random() * (array.length + 1));
2024-08-06 17:49:02 -07:00
const newItem = getRandomItemName();
2024-08-06 17:13:43 -07:00
if (insertBefore === 0) {
return [newItem, ...array];
}
return [
...array.slice(0, insertBefore),
newItem,
...array.slice(insertBefore),
];
}
function removeRandomlyFromArray(array: string[]): string[] {
const removeIndex = Math.floor(Math.random() * array.length);
if (removeIndex === 0) {
return [...array.slice(1)];
}
if (removeIndex === array.length) {
return [...array.slice(0, -1)];
}
return [...array.slice(0, removeIndex), ...array.slice(removeIndex + 1)];
}
2024-08-06 16:26:30 -07:00
export const AnimatedListDemo = () => {
2024-08-06 16:36:00 -07:00
const [items, mutateItems] = useReducer(
(prevState: string[], mutation: Mutation) => {
2024-08-06 17:13:43 -07:00
let newState: string[] = [...prevState];
2024-08-06 16:36:00 -07:00
switch (mutation) {
case 'reverse':
newState.reverse();
2024-08-06 17:13:43 -07:00
break;
case 'randomize':
shuffleArray(newState);
break;
case 'insert':
newState = insertRandomlyIntoArray(newState);
break;
case 'remove':
newState = removeRandomlyFromArray(newState);
break;
2024-08-06 16:36:00 -07:00
default:
return prevState;
}
2024-08-06 17:13:43 -07:00
return newState;
2024-08-06 16:36:00 -07:00
},
2024-08-06 17:49:02 -07:00
new Array(4).fill('').map(() => getRandomItemName()),
2024-08-06 16:36:00 -07:00
);
const { updateItemRef, updateItemPositions, itemStyles } =
useAnimatedListItems({ keys: items });
return (
2024-08-06 19:19:52 -07:00
<>
<div className="buttons">
<button
type="button"
onClick={() => {
updateItemPositions();
mutateItems('reverse');
}}
>
Reverse
</button>
<button
type="button"
onClick={() => {
updateItemPositions();
mutateItems('randomize');
}}
>
Randomize
</button>
<button
type="button"
onClick={() => {
updateItemPositions();
mutateItems('insert');
}}
>
Insert
</button>
<button
type="button"
onClick={() => {
updateItemPositions();
mutateItems('remove');
}}
>
Remove
</button>
</div>
2024-08-06 16:36:00 -07:00
<ol>
{items.map((item) => {
return (
<li
key={item}
ref={(li) => updateItemRef(item, li)}
style={itemStyles[item]}
>
{item}
</li>
);
})}
</ol>
2024-08-06 19:19:52 -07:00
</>
2024-08-06 16:36:00 -07:00
);
2024-08-06 16:26:30 -07:00
};