From 26fae13c8ebd3f11f134c3bc0edfc971afd42fff Mon Sep 17 00:00:00 2001 From: AAGaming Date: Tue, 21 Feb 2023 22:36:56 -0500 Subject: [PATCH] feat(ReorderableList): add animations, clean up --- src/custom-components/ReorderableList.tsx | 62 ++++++++++++++++------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/src/custom-components/ReorderableList.tsx b/src/custom-components/ReorderableList.tsx index 8c9445f..06eb023 100644 --- a/src/custom-components/ReorderableList.tsx +++ b/src/custom-components/ReorderableList.tsx @@ -1,4 +1,4 @@ -import { CSSProperties, Fragment, JSXElementConstructor, ReactElement, useEffect, useState } from 'react'; +import { Fragment, JSXElementConstructor, ReactElement, useEffect, useState } from 'react'; import { Field, FieldProps, Focusable, GamepadButton } from '../deck-components'; @@ -16,12 +16,15 @@ export type ReorderableEntry = { /** * Properties for a ReorderableList component of type . + * + * @param animate If the list should animate. @default true */ -type ListProps = { +export type ReorderableListProps = { entries: ReorderableEntry[]; onSave: (entries: ReorderableEntry[]) => void; interactables?: JSXElementConstructor<{ entry: ReorderableEntry }>; fieldProps?: FieldProps; + animate?: boolean; }; /** @@ -29,7 +32,8 @@ type ListProps = { * * See an example implementation {@linkplain https://github.com/Tormak9970/Component-Testing-Plugin/blob/main/src/testing-window/ReorderableListTest.tsx here}. */ -export function ReorderableList(props: ListProps) { +export function ReorderableList(props: ReorderableListProps) { + if (props.animate === undefined) props.animate = true; const [entryList, setEntryList] = useState[]>( props.entries.sort((a: ReorderableEntry, b: ReorderableEntry) => a.position - b.position), ); @@ -69,6 +73,7 @@ export function ReorderableList(props: ListProps) { > {entryList.map((entry: ReorderableEntry) => ( (props: ListProps) { /** * Properties for a ReorderableItem component of type */ -type ListEntryProps = { +export type ReorderableListEntryProps = { fieldProps?: FieldProps; listData: ReorderableEntry[]; entryData: ReorderableEntry; reorderEntryFunc: CallableFunction; reorderEnabled: boolean; + animate: boolean; children: ReactElement | null; }; -function ReorderableItem(props: ListEntryProps) { +function ReorderableItem(props: ReorderableListEntryProps) { + const [isSelected, _setIsSelected] = useState(false); + const [isSelectedLastFrame, setIsSelectedLastFrame] = useState(false); const listEntries = props.listData; function onReorder(e: Event): void { @@ -129,22 +137,38 @@ function ReorderableItem(props: ListEntryProps) { ); } - const baseCssProps: CSSProperties = { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - width: '100%', - }; + async function setIsSelected(val: boolean) { + _setIsSelected(val); + // Wait 3 frames, then set. I have no idea why, but if you dont wait long enough it doesn't work. + for (let i = 0; i < 3; i++) await new Promise((res) => requestAnimationFrame(res)); + setIsSelectedLastFrame(val); + } return ( - - {props.children} - + setIsSelected(false)} + onGamepadFocus={() => setIsSelected(true)} + > + {props.children} + + ); }