demo working with the first action

This commit is contained in:
Matthew Cardarelli 2024-08-06 16:36:00 -07:00
parent 648f9464cb
commit e3635677d5
3 changed files with 54 additions and 11 deletions

View File

@ -1,5 +1,50 @@
import React from 'react';
import React, { useReducer } from 'react';
import { useAnimatedListItems } from './useAnimatedListItems';
type Mutation = 'reverse' | 'randomize' | 'insert' | 'remove';
export const AnimatedListDemo = () => {
return <main>Hello, world</main>;
const [items, mutateItems] = useReducer(
(prevState: string[], mutation: Mutation) => {
switch (mutation) {
case 'reverse':
const newState = [...prevState];
newState.reverse();
return newState;
default:
return prevState;
}
},
['Item 0', 'Item 1', 'Item 2', 'Item 3'],
);
const { updateItemRef, updateItemPositions, itemStyles } =
useAnimatedListItems({ keys: items });
return (
<main>
<ol>
{items.map((item) => {
return (
<li
key={item}
ref={(li) => updateItemRef(item, li)}
style={itemStyles[item]}
>
{item}
</li>
);
})}
</ol>
<button
type="button"
onClick={() => {
updateItemPositions();
mutateItems('reverse');
}}
>
Reverse
</button>
</main>
);
};

View File

@ -10,7 +10,6 @@ class AnimatedListComponent extends HTMLElement {
}
connectedCallback() {
console.log('Hello, world!');
const rootNode = document.createElement('main');
this.appendChild(rootNode);
this.root = createRoot(rootNode);

View File

@ -1,15 +1,15 @@
import { useLayoutEffect, useRef, useState } from 'react';
interface ItemTops {
[id: number]: number | undefined;
[id: string]: number | undefined;
}
interface ListItemRefsById {
[id: number]: HTMLLIElement | undefined;
[id: string]: HTMLLIElement | undefined;
}
interface ItemOffsets {
[id: number]: number | undefined;
[id: string]: number | undefined;
}
interface ItemStyles {
@ -26,7 +26,7 @@ interface UseAnimatedListItemArgs {
* The list of item keys. Each key should uniquely identify a `<ListItem>` component, and
* should be the same value passed to the `ListItem`'s `key` prop.
*/
keys: number[] | undefined;
keys: string[] | undefined;
}
interface UseAnimatedListItemReturns {
@ -34,16 +34,16 @@ interface UseAnimatedListItemReturns {
* Item styles that should be passed to the `sx` prop of each `ListItem`. The styles are
* mapped per item key.
*/
itemStyles: { [key: number]: ItemStyles | undefined };
itemStyles: { [key: string]: ItemStyles | undefined };
/**
* Function that must be called within the `ref` callback prop of each `ListItem`.
*
* @param {number} key - the `ListItem`'s unique key.
* @param {string} key - the `ListItem`'s unique key.
* @param {HTMLLIElement} li - the list item element reference.
* @returns {void}
*/
updateItemRef: (key: number, li: HTMLLIElement | null) => void;
updateItemRef: (key: string, li: HTMLLIElement | null) => void;
/**
* Function that must be called within each and every callback that causes the list of items
@ -68,7 +68,6 @@ export const useAnimatedListItems = ({
useLayoutEffect(() => {
if (!keys) return;
const newItemOffsets: ItemOffsets = {};
keys.forEach((key) => {
const itemRef = itemRefs.current[key];